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

6 réponses

1 2 3
Avatar
Jean-Marc Bourguet
Emmanuel Delahaye writes:

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
^^^^^^^^^^^^^^^^^


A+

--
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
Antoine Leca
In news:43a5cf57$0$15437$,
Emmanuel Delahaye va escriure:
T'es assis ?


Il n'y a que les grand gourous qui tapent sur un clavier en étant debouts.


-Wconversion


La semaine dernière on avait un fil sur ce sujet, qui montrait ÀMHA assez
clairement que cet avertissement n'était pas nécessaire aujourd'hui (ou sur
du code un tant soit peu actuel). Il sert surtout à détecter du code qui ne
passerait pas bien sur un compilateur pré-ANSI.


Antoine

Avatar
Antoine Leca
In news:20051218052451$,
Vincent Lefevre va escriure:
typedef int TBOOLEAN;
[...]
extern TBOOLEAN screen_ok;


Pas de déclaration précédente, déclaration avec liaison externe.
Cf. 6.2.2p4, dernière phrase.

[...]
TBOOLEAN screen_ok;


Déclaration avec liaison externe, 6.2.2p5, deuxième phrase.
C'est aussi une tentative de définition, 6.9.2p2, première phrase.


S'il n'y a rien d'autre concernant screen_ok (par exemple, pas de lignes qui
se lirait
TBOOLEAN screen_ok = 1;
dans un fichier .c qui #inclurait "Gnuplot.h"), cette tentative devient une
définition externe (6.9.2p3, seconde phrase), avec valeur d'initialisation
0.

Au total, aucun problème vis-à-vis de la norme.


La ligne "TBOOLEAN screen_ok;" est probablement une erreur,


Effectivement, au niveau du style, une tentative de déclaration dans un
entête, ce n'est pas conseillé, car le comportement n'est pas facilement
prévisible (non portable).
En particulier, sur Unix cela sera l'équivalent d'une déclaration externe et
c'est l'éditeur de liens qui va transformer les tentatives de *toutes* les
unités en une seule définition, comme un COMMON Fortran; avec d'autres
systèmes, si le même entête est #inclus dans deux ou plusieurs unités, tu
auras une erreur de redéfinition à l'unité de liens.
Il y a des explications détaillées à ce sujet dans le Rationale.


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)?


Comportement indéfini. Violation de "shall" dans 6.9p5, /Semantics/ (donc ce
n'est pas une contrainte, pas de diagnostic requis) :
If an identifier declared with external linkage is used in an
expression (other than as part of the operand of a *sizeof*
operator whose result is an integer constant), somewhere in
the entire program there shall be exactly one external
definition for the identifier; otherwise, there shall be no
more than one.<FOOTNOTE>Thus, if an identifier declared with
external linkage is not used in an expression, there need be
no external definition for it.</FOOTNOTE>


À cause de cette ligne, le linkeur se plaint:


Cas classique hors Unix.

Je n'arrive pas à la reproduire sur un exemple simple.


Essaye de récupérer le compilo C du musée de Borland : celui-ci n'implémente
pas la sémantique Unix (variable COMMON), contrairement à celui de MS ou à
GCC/binutils (je crois), et donc va te faire la même erreur (à l'édition de
liens) sur des exemples mêmes simples.

/* fich1.c */
int screen_ok;

/* fich2.c */
int screen_ok;


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


Mmmh. Révise bien ton source, alors.
Soit cette variable n'est pas _utilisée_ du tout, et on est dans le cas de
la note de bas de page ci-dessus (il n'est pas nécessaire d'avoir une
définition).
Soit elle est utilisée quand même, et il faut quelque part une définition
pour initialiser l'objet (sauf éditeur de liens « intelligent » qui fournit
automatiquement une tentative, et ce n'est *pas* le comportement classique).


Antoine

Avatar
Antoine Leca
In news:43a52d93$0$9487$,
Emmanuel Delahaye va escriure:
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
Linking console executable: C:devforumsOP1.exe
Process terminated with status 0 (0 minutes, 0 seconds)
0 errors, 2 warnings

Ce warning me suffit pour considérer qu'il y a un problème.


Certes, mais ce n'est *pas* le même problème que celui de Vincent.


D'autres compilateurs pourraient rejeter ce code.


Dans un mode non conforme à la norme C, alors.
On a ici deux tentatives, qui sont donc résolues en une déclaration externe
à la fin de la compilation.



Antoine

Avatar
DINH Viêt Hoà

In news:43a5cf57$0$15437$,
Emmanuel Delahaye va escriure:
T'es assis ?


Il n'y a que les grand gourous qui tapent sur un clavier en étant debouts.


c'est France Gall qui disait ça ?

--
DINH V. Hoa,

"Le monde n'attend que toi ! " -- FiLH


Avatar
Vincent Lefevre
Dans l'article <do61hu$oia$,
Antoine Leca écrit:

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)?


Comportement indéfini. Violation de "shall" dans 6.9p5, /Semantics/
(donc ce n'est pas une contrainte, pas de diagnostic requis) :
[...]


Merci. Y a-t-il une option de gcc permettant d'avoir systématiquement
un diagnostic dans ce cas-là? (Enfin, je suppose qu'une telle option
devra être passée, éventuellement sous une autre forme, au linkeur,
i.e. le linkeur doit supporter une telle vérification.)

À cause de cette ligne, le linkeur se plaint:


Cas classique hors Unix.


En fait, c'est un Unix (Mac OS X). Mais le linkeur est ici appelé
avec des options spécifiques à Mac OS X, ce qui change probablement
le comportement par rapport au "comportement Unix" qui consiste à
ne rien dire.

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


Mmmh. Révise bien ton source, alors.
Soit cette variable n'est pas _utilisée_ du tout, et on est dans le
cas de la note de bas de page ci-dessus (il n'est pas nécessaire
d'avoir une définition).


C'est effectivement le cas: ça compile même si j'enlève toute
déclaration de cette variable de "Gnuplot.h".

--
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


1 2 3