OVH Cloud OVH Cloud

probleme de declaration/definition de variables et linkage

26 réponses
Avatar
Vincent Lefevre
Bonjour,

Dans

http://search.cpan.org/CPAN/authors/id/I/IL/ILYAZ/modules/Term-Gnuplot-0.5705.tar.gz

il y a un fichier Gnuplot.h contenant en particulier:

typedef int TBOOLEAN;
[...]
extern TBOOLEAN screen_ok;
[...]
TBOOLEAN screen_ok;

La ligne "TBOOLEAN screen_ok;" est probablement une erreur, mais
quelle est son effet du point de vue de la norme, sachant qu'on
a la même chose ailleurs et que les deux fichiers objets seront
linkés ensemble (cf ci-dessous)?

À cause de cette ligne, le linkeur se plaint:

LD_RUN_PATH="/opt/local/lib" env MACOSX_DEPLOYMENT_TARGET=10.3 cc -L/opt/local/lib -bundle -undefined dynamic_lookup -L/usr/local/lib Gnuplot.o -o blib/arch/auto/Term/Gnuplot/Gnuplot.bundle ./gnuterm/libgnuterm.a -lm -lgd -lpng -lz
/usr/bin/ld: multiple definitions of symbol _screen_ok
Gnuplot.o definition of _screen_ok in section (__DATA,__common)
./gnuterm/libgnuterm.a(util.o) definition of _screen_ok in section (__DATA,__common)
collect2: ld returned 1 exit status

Une telle erreur est-elle normale (source C incorrect) ou s'agit-il
d'un bug de l'implémentation? Je n'arrive pas à la reproduire sur
un exemple simple.

Note: je dis bien "à cause de cette ligne", car si je l'enlève,
je n'ai plus d'erreur.

--
Vincent Lefèvre <vincent@vinc17.org> - Web: <http://www.vinc17.org/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/>
Work: CR INRIA - computer arithmetic / SPACES project at LORIA

10 réponses

1 2 3
Avatar
Emmanuel Delahaye
A un moment j'écrivais des trucs du style :

-----
// truc.h
#ifdef GENERATE
#define EXTERN
#else
#define EXTERN extern
endif


Horrible et inutile!

J'ai abandonné cette pratique, mais je ne sais plus bien pourquoi, sans
doute simplement parce que je n'utilise pas les extern.


Tu as bien fait. Pas la peine d'encourager l'utilisation des variables
globales...

--
A+

Emmanuel Delahaye

Avatar
Harpo
Emmanuel Delahaye wrote:

On peut aussi se poser le problème des variables automatiques,
sont-elle réservées à leur définition ?


J'ai rien compris, mais oui!


Maintenant, le problème concerne donc la signification du mot
réservation !


Avatar
Harpo
Emmanuel Delahaye wrote:

A un moment j'écrivais des trucs du style :

-----
// truc.h
#ifdef GENERATE
#define EXTERN
#else
#define EXTERN extern
endif


Horrible


Soit ! C'est un point de vue.

et inutile!


Non, car cela permet que la variable soit définie avec le même type avec
lequel elle a été déclarée. Par exemple dans le cas du 'EXTERN int a;',
si on veut que a soit un long, il n'y a seulement 3 caractères à
remplacer par 4; et cela diminue par 2 la charge de travail ! Sans
parler du risque d'erreurs !
Mon souci était de ne faire qu'une fois ce qui pouvais n'être fait
qu'une fois.


J'ai abandonné cette pratique, mais je ne sais plus bien pourquoi,
sans doute simplement parce que je n'utilise pas les extern.


Tu as bien fait. Pas la peine d'encourager l'utilisation des variables
globales...


En règle générale oui, mais elle peuvent être utiles dans certain cas et
ne sont pas amha dangereuses quand il s'agit de constantes.
Sinon, il faut être certain que son petit programme qui lit un fichier A
et écrit un fichier B qui est en fait le fichier A zorglublifié ne sera
pas modifié par quelqu'un qui aura inventé la zorglublification
parallèle et y mettra des threads.


Avatar
Vincent Lefevre
Dans l'article <43a5793e$0$29212$,
Harpo écrit:

Notons que même Gcc s'est laissé avoir, dans ton exemple donné
précédemment, il dit:

int a;
int a;

int main(void)
{
return 0;
}

Compiling: main.c
main.c:8: warning: redundant redeclaration of 'a'
main.c:7: warning: previous declaration of 'a' was here


Comment fais-tu pour avoir un warning avec gcc sur ce code-là?
Je n'ai aucun warning, même avec gcc -Wall -Wextra.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/>
Work: CR INRIA - computer arithmetic / SPACES project at LORIA

Avatar
Harpo
Vincent Lefevre wrote:

Dans l'article <43a5793e$0$29212$,
Harpo écrit:

Notons que même Gcc s'est laissé avoir, dans ton exemple donné
précédemment, il dit:

int a;
int a;

int main(void)
{
return 0;
}

Compiling: main.c
main.c:8: warning: redundant redeclaration of 'a'
main.c:7: warning: previous declaration of 'a' was here


Comment fais-tu pour avoir un warning avec gcc sur ce code-là?
Je n'ai aucun warning, même avec gcc -Wall -Wextra.


Je n'y arrive pas, c'est Emdel qui l'a eu.
Peut-être un pb de version, chez moi :
$ gcc --version
gcc (GCC) 4.0.3 20051201 (prerelease) (Debian 4.0.2-5)
(snip blah)

Ca me fait penser que je dois faire mon upgrade du dimanche...


Avatar
Harpo
Harpo wrote:


Comment fais-tu pour avoir un warning avec gcc sur ce code-là?
Je n'ai aucun warning, même avec gcc -Wall -Wextra.


Je n'y arrive pas, c'est Emdel qui l'a eu.


Bien pis, je n'arrive pas avoir de message au link de ces 2 programmes :
----
// redeclO1.c
#include <stdio.h>
extern int a;
int a;
int main(){
a = 1;
fprintf( stdout, "%dn", a );
return 0;
}
----
// redecl02.c
extern int a;
int a;
----
$ gcc -c -W -Wall -o redecl01.o
$ gcc -c -W -Wall -o redecl01.o
$ gcc redecl01.o redecl02.o -o redecl
$ ./redecl
1
$
Il va falloir que je regarde la map du programme pour dormir tranquille.


Avatar
Jean-Marc Bourguet
Vincent Lefevre <vincent+ writes:

Dans l'article <43a5793e$0$29212$,
Harpo .ANicrit:

Notons que m.ANjme Gcc s'est laiss.ANi avoir, dans ton exemple donn.ANi
pr.ANic.ANidemment, il dit:

int a;
int a;

int main(void)
{
return 0;
}

Compiling: main.c
main.c:8: warning: redundant redeclaration of 'a'
main.c:7: warning: previous declaration of 'a' was here


Comment fais-tu pour avoir un warning avec gcc sur ce code-l.AN`?
Je n'ai aucun warning, m.ANjme avec gcc -Wall -Wextra.


[~/src]$ cat dub.c
int a;
int a;

int main(void)
{
return 0;
}
[~/src]$ gcc -stdÉ9 -pedantic-errors -Wall -Wextra -c dub.c
[~/src]$ g++ -c dub.c
dub.c:2: erreur: redefinition of $B!F(Bint a$B!G(B
dub.c:1: erreur: $B!F(Bint a$B!G(B previously declared here

Mais c'est une erreur, pas un warning (j'adore la
localisation de gcc, ils devraient arr.ANjter de pr.ANitendre
qu'ils en font).

Au link, les .ANiditeurs de liens sous Unix ignorent
traditionnellement les d.ANifinitions dupliqu.ANies (certains
donnent des avertissements si les tailles ne correspondent
pas, mais pas tous). Mais .AN` la compilation aucune id.ANie.

Antoine, peut-.ANjtre?

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Harpo
Jean-Marc Bourguet

a$B!G(B
dub.c:1: erreur: $B!F(Bint a$B!G(B previously declared here


Mais c'est une erreur, pas un warning (j'adore la
localisation de gcc, ils devraient

arr(B?????????????????????????????????????????????????????????????????????????(B


Warning : Line too long or unrecognized charset or something else.
(verbosely truncated)

Sur le petit test pr(B?(Bc(B?(Bdent, j'ai
$ objdump -t redecl01.p

redecl01.o: file format elf32-i386

SYMBOL TABLE:
00000000 l df *ABS* 00000000 redecl01.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .rodata 00000000 .rodata
00000000 l d .note.GNU-stack 00000000 .note.GNU-stack
00000000 l d .comment 00000000 .comment
00000000 g F .text 0000004a main
00000004 O *COM* 00000004 a
00000000 *UND* 00000000 stdout
00000000 *UND* 00000000 fprintf

et l'(B?(Bquivalent pour a dans redecl02.o, je n'ai plus en t(B?(Bte le format
de sortie de objdump, mais il semble qu'il mette tout ce qui est
d(B?(Bclar(B?(B au plus haut niveau et non-static dans une m(B?(Bme section COM, le
fait que ce soit red(B?(Bfini ne l'importune pas.
Demain je regarderai en initialisant a, c'est cela qui devrait causer
probl(B?(Bme.


Avatar
Emmanuel Delahaye

MIME-Version: 1.0
Content-Type: text/plain; charset=iso-2022-jp-2

T'ain, c'est quoi ce cirque !

--
A+

Emmanuel Delahaye
Avatar
Emmanuel Delahaye
int a;
int a;

int main(void)
{
return 0;
}



Compiling: main.c
main.c:8: warning: redundant redeclaration of 'a'
main.c:7: warning: previous declaration of 'a' was here


Comment fais-tu pour avoir un warning avec gcc sur ce code-là?
Je n'ai aucun warning, même avec gcc -Wall -Wextra.


T'es assis ?

-O2 -Wchar-subscripts -Wcomment -Wformat=2 -Wimplicit-int
-Werror-implicit-function-declaration -Wmain -Wparentheses
-Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs -Wunused
-Wuninitialized -Wunknown-pragmas -Wfloat-equal -Wundef
-Wshadow -Wpointer-arith -Wbad-function-cast -Wwrite-strings
-Wconversion -Wsign-compare -Waggregate-return -Wstrict-prototypes
-Wmissing-prototypes -Wmissing-declarations -Wmissing-noreturn
-Wformat -Wmissing-format-attribute -Wno-deprecated-declarations
-Wpacked -Wredundant-decls -Wnested-externs -Winline -Wlong-long

Amen !

--
A+

Emmanuel Delahaye


1 2 3