Il semble que la variable globale ininitialisée est traitée comme un symbole faible dans la GCC. Quelle est la raison derrière cela? P>
4 Réponses :
est-ce ce que vous vouliez dire?
faim.c p> fort.c p> échantillon p> le int faible; code> dans faible.c est une déclaration, pas une définition. strong> ou vous peut dire que c'est une définition provisoire. La définition réelle est dans
forte.c code> lorsque ce fichier d'objet est lié dans le programme final strong> ou dans
faibles.c code> sinon. s>
Ceci est une extension commune que GCC utilise (merci Andrey). P> p>
Pas vrai. int faible code> dans
faibles.c code> est une définition. Un provisoire, mais la définition néanmoins. Le programme ci-dessus fait i> violer les règles de la langue, mais est pris en charge comme une extension non standard.
globaux non initialisés qui ne sont pas déclarés GCC, en mode C ++: strong> p> Pas la même chose - ça ne fait pas la chose des symboles communs. Les globaux "nonInsialisés" qui ne sont pas déclarés dans les deux cas, un faible Le symbole permet un symbole initialisé d'être remplacé par un symbole initialisé non faible du même nom au moment de la liaison. P> Pour illustrer (concentrer sur le boîtier C ici), je vais utiliser 4 variantes d'un programme principal, qui sont tous identiques, à l'exception de la manière dont main_init.c strong>: p>
main_uninit.c strong>, qui omet l'initialisation: p>
Main_uninit_extern.c strud>, qui ajoute le mot-clé extern code> sont traités comme des symboles "communs", pas des symboles faibles. P> Les symboles communs sont fusionnés au moment de la liaison afin qu'ils se réfèrent tous au même stockage; Si plus d'un objet tente d'initialiser un tel symbole, vous obtiendrez une erreur de temps de liaison. (S'ils ne sont pas explicitement initialisés nulle part, ils seront placés dans la BSS, c'est-à-dire initialement initialisé à 0.) p>
extern code> sont implicitement initialisés à une valeur par défaut (0 pour des types simples ou constructeur par défaut). P>
global code> est déclaré: p>
$ gcc -o test main_init_weak.c another_def.c && ./test
1234
$ gcc -o test main_init_weak.c && ./test
999
extern code>: p>
$ gcc -o test main_uninit_extern.c another_def.c && ./test
1234
global code> et le décrit comme un symbole faible: p>
$ gcc -o test main_uninit_extern.c && ./test
/tmp/ccqdYUIr.o: In function `main':
main_uninit_extern.c:(.text+0x12): undefined reference to `global'
collect2: ld returned 1 exit status
Grande explication avec des exemples. Pourriez-vous également inclure la faible interaction avec des fonctions?
@Maciej - Bon point, j'ai oublié que ceci a été tagué avec les deux lors de la rédaction de ma réponse à l'origine! Non, ce n'est pas la même chose pour C ++, j'ai donc mis à jour ma réponse en conséquence.
@Tomek - Les fonctions faibles sont similaires: si la lieur voit à la fois une définition faible d'une fonction et une forte (normale), elle résoudra des références non définies à la forte et ignorez le faible. Si cela ne voit qu'une définition faible, cela utilisera cela comme si c'était une normale.
Cette explication peut être prise comme une description du comportement spécifique du compilateur. Il est incorrect b> comme une description du comportement du langage C. C langue interdit i> Définitions multiples des entités avec un lien externe (juste comme C ++ fait). Le comportement observé n'est rien de plus qu'une extension de compilateur.
De plus, il convient de noter qu'en C, comme en C ++, les variables globales non initialisées sont implicitement initialisées avec 0. Pour une raison quelconque, le libellé de la réponse ci-dessus semble le présenter comme une différence entre C et C ++.
@Andreyt Droite, mais la question pose spécifiquement de questions sur le GCC et les symboles faibles, c'est une question de liaison / compilateur / mise en œuvre, pas une question de langue et ceci est une réponse appropriée IMO.
@Logan Capaldo: Je suis d'accord, la réponse est appropriée. Peut-être que je n'ai mal compris que les légendes "en C" et "en C ++". Ont-ils voulu faire référence à "GCC en mode C" et "GCC en mode C ++"?
@Andreyt: Oui (comme la question pose de manière très spécifiquement posée à propos de GCC). Je suppose que cela se lit mieux avant que je sois modifié plus tôt pour noter la différence C vs. C ++. J'ai encore modifié pour préciser que je parle de GCC. (En ce qui concerne votre autre point: j'ai également dit à l'origine que des symboles communs inintitualisés se retrouvent dans la BSS. J'ai également déménagé que vers le haut.)
Toute définition multiple d'un symbole global est un comportement indéfini, de sorte que GCC (ou plutôt le lieur de GNU Binutils) est libre de faire ce qu'il veut. En pratique, il suit le comportement traditionnel pour éviter de casser le code qui repose sur ce comportement. P>
Voulez-vous dire multiple définition b>?
La question est basée sur une prémisse incorrecte. Les variables mondiales non initialisées ne sont pas des symboles faibles. P>
Apparemment, la question fait référence à la possibilité de définir le même objet non initialisé avec une liaison externe dans plusieurs unités de traduction. Formellement, il n'est pas autorisé - c'est une erreur de C et C ++. Cependant, au moins en C est reconnu par C99 Standard comme "extension commune" de la langue, mise en œuvre dans de nombreux compilateurs de la vie réelle p>
j.5 extensions communes forte> p>
J.5.11 Plusieurs définitions externes forte> p>
1 fort> il peut y avoir plus d'un externe Définition pour l'identifiant d'un objet, avec ou sans l'explicite Utilisation du mot-clé extérieur; si la les définitions sont en désaccord, ou plus d'un est initialisé, le comportement est indéfini (6.9.2). P> blockQuote> Note, qui contrairement à la croyance populaire, C Langue C interdit explicitement l'introduction de multiples définitions d'entités avec des liaisons externes dans le programme, tout comme C ++. P>
6.9 Définitions externes strong> p>
5 forte> une définition externe est une Déclaration externe qui est aussi une définition d'une fonction (autre que une définition en ligne) ou un objet. Si Un identifiant déclaré avec externe Linkage est utilisé dans une expression (autre que dans le cadre de l'opérande de un opérateur de taille dont le résultat est un entière constante), quelque part dans le tout le programme doit être exactement une définition externe forte> pour le identifiant; Sinon, il doit y avoir pas plus d'un fort>. p> blockQuote> Cependant, l'extension permettant cela a été assez populaire avec de nombreux compilateurs C, dont GCC se trouve être un. P>
La fonction de support de liaison est requise pour mettre en œuvre des blocs communs fortrains. Vous remarquerez que GCC comprend un compilateur Fortran dans la collection. Étant donné que les bibliothèques de soutien sont implémentées dans C, il n'est pas surprenant qu'il existe une petite quantité de fuites inoffensifs de la liaison.
Pouvez-vous donner un exemple de définition externe et de déclaration externe?
Ce n'est pas seulement des fonctions en ligne de Fortran, C ++ et des modèles implicitement instanciés sont également faibles.
Comment venez-vous à cette conclusion, qu'est-ce que vous avez essayé, quels sont les faits?
C ou C ++? Il y a une grande différence.
@Andreyt: in c,
int n; code> au champ d'application du fichier est une définition provisoire et une extension commune (Annexe J), que GCC suit, pour permettre à plusieurs définitions dans une seule unité de traduction (comme dans Standard c) et entre les unités de traduction tant que les définitions sont d'accord et à la plupart d'une définition ne sont pas provisoires. En C ++
INT N; CODE> est juste une définition, il n'y a pas de concept provisoire, et il n'est pas courant de permettre et de fusionner plusieurs définitions dans un programme. Les versions de GCC que j'ai utilisées ne l'ont pas laissée en mode C ++, donc mon interrogation si la balise C ++ était vraiment appropriée.
@Andreyt: Je viens de lire votre réponse. Clairement, vous savez tout cela déjà. Pourquoi prendre la peine de me demander et susciter la longue explication?
@Chals Bailey: Eh bien, pour moi, le concept de définition provisoire semble avoir uniquement un effet local (restreint à une unité de traduction) et qu'il ne ressemble donc pas à quelque chose de pertinent dans ce cas. Ainsi, lorsqu'il s'agit de problèmes d'unité inter-traduction (que cette question semble être à propos de), je ne vois aucune différence notable entre C et C ++ (en dehors de la remarque «Extension commune»). La raison pour laquelle j'ai demandé est parce que je pensais que cela me manque peut-être autre chose.