7
votes

Erreur de symbole dupliquée associée à la déclaration de const Char * []

J'adorerais aider à diagnostiquer la source d'une erreur de symbole dupliquée que je reçois lorsque j'essaie de compiler avec g ++ 4.2.1.

L'erreur spécifique est xxx

L'erreur se produit uniquement lorsque j'inclus cette déclaration dans un fichier appelé paramètre.h : : : : xxx

J'ai recherché tous mes fichiers, et c'est le seul endroit où sociodem_filenames est déclaré. Lorsque je commente la déclaration, l'erreur «symbole dupliquée» disparaît.

Je suis inconnu avec des erreurs de liaison (si c'est ce que cela est) et apprécierait l'aide pour résoudre le problème. Tous mes fichiers d'en-tête ont #ifndef ... # définir ... # endif wrappers. Ma commande compile est xxx

merci d'avance. <<


Résumé de la solution

i ont maintenant dans les paramètres.h: xxx

toutes les autres définitions et déclarations dans les paramètres.h sont inchangées. Andrey et d'autres commentateurs résument une approche alternative utilisant externe , qui est excédant à mes fins.


2 commentaires

Super. Pourtant, je ne comprends toujours pas pourquoi vous ne déclarez pas votre sociodem_filenames tableau comme const . Les entrées de réseau sont-elles censées être modifiables au moment de l'exécution?


@Andrey: Je devrais les déclarer comme constante. Merci.


5 Réponses :


2
votes

La garde d'en-tête ( #Ifndef .. # endif wrapper) vous empêche d'inclure la même en-tête plusieurs fois dans un seul fichier source. Vous pouvez toujours avoir plusieurs fichiers source incluant cet en-tête et chacun déclarera ce symbole séparément. Comme ils ont tous le même nom, lier ces sources ensemble provoquera une collision de noms de symboles. Vous voulez probablement déclarer le symbole dans un fichier source au lieu d'un fichier d'en-tête


0 commentaires

2
votes

Le problème est que vous mettez une définition dans un fichier d'en-tête. Si vous incluez ce fichier dans plusieurs unités de compilation (fichier .cpp), vous obtiendrez de multiples définitions et au moment de la liaison, vous obtiendrez cette erreur.

Vous devez mettre à la fois ces définitions dans un fichier .CPP et Mettez Seulement une déclaration dans le fichier d'en-tête: xxx


0 commentaires

7
votes

Très probablement, vous êtes #include ce fichier dans plusieurs fichiers source. Le problème est que chaque inclusion entraîne une définition distincte pour une variable nommée sociodem_filenames . Inclure les gardes n'aident pas avec cela. Inclure les gardes empêchent de multiples déclarations dans une seule unité de compilation; ils n'empêchent pas plusieurs définitions sur plusieurs unités de compilation.

Ce que vous devez faire est de déclarer ces variables comme extern dans l'en-tête, puis de les définir exactement fichier source. par exemple xxx

et ensuite: xxx

Vous pouvez vous échapper sans le faire pour le int Parce qu'il s'agit d'un entier constant, le compilateur peut donc simplement le traiter comme une constante de temps de compilation, et elle ne se présentera même jamais dans le code compilé. Cependant, le Char * ne peut pas être traité de cette manière, et doit donc avoir exactement une définition (appelée «règle de définition» en C ++).


3 commentaires

Qu'entendez-vous par les paramètres Int et Double «N'ayez même jamais montré [ING] dans le code compilé»? Tous mes autres paramètres étaient de type numérique constant et semblaient être présents dans le code compilé.


Je veux dire que le compilateur n'a pas nécessairement besoin de créer des emplacements de mémoire pour stocker ces chiffres lorsque le programme est exécuté. Essentiellement, le compilateur peut le traiter presque comme si vous écrivez #define num_sociodem_files 5 et il suffit de remplacer la variable avec le littéral 5 où qu'il soit utilisé. La règle d'une définition existe pour que chaque variable nommée puisse être mappée sur un emplacement de mémoire unique et unique. Si un emplacement de mémoire n'est pas requis, le problème est moot.


Déplacement de la définition num_sociiodem_files sur le fichier .cpp est en réalité une mauvaise idée. Les objets Const Scalar sont normalement définis dans les fichiers d'en-tête. Il n'y a rien de mal à cela et en fait, il y a beaucoup de choses avec ça. Dans de nombreux cas, il est extrêmement utile d'avoir num_sociodem_files comme une expression constante intégrale. Cette réponse a détruit cette valeur précieuse de num_sociodem_files sans raison.



2
votes

Comme d'autres ont suggéré, une façon de le faire est de déclarer num_sociodem_files et sociodem_filenames comme extern et les définir une fois dans un fichier externe . L'autre sens est de les déclarer comme statique - cela leur permet d'être dupliqués dans chaque fichier d'objet qui inclut l'en-tête, mais ne créera pas d'erreur car la définition est privée dans ce fichier d'objet. Quelle option que vous choisissez est entièrement à vos préférences.


4 commentaires

Merci. N'avait pas su cette option.


C'est dangereux si vous ne comprenez pas complètement ce que cela signifie - cela crée une instance séparée de ces variables dans chaque fichier d'objet. C'est probablement bien (bien que peu inefficace) dans ce cas, puisqu'il s'agit de Const, mais si vous l'avez fait avec une variable mutable et l'a changé dans un fichier, seule l'instance de ce fichier changerait


Je ne prévoyais pas d'aller dans cette voie pour cette raison, mais je n'ai pas réalisé que «statique» créerait des copies distinctes pour chaque fichier. J'apprécie l'avertissement.


@Sarah Static signifie que le symbole est local dans le fichier d'objet qui le contient. Il "corrige" l'erreur car maintenant tous vos fichiers source ont toujours les mêmes symboles avec le même nom, mais les symboles sont locaux au lieu de Global pour ne pas entrer en collision entre eux.



14
votes

Pour une raison quelconque, aucune des réponses ne se souciait jusqu'à présent d'expliquer la différence entre votre entier num_sociiodem_files objet et tableau sociodem_filenames objet. Ce dernier déclenche l'erreur de liaison pour les raisons déjà expliquées: parce que vous incluez votre fichier d'en-tête en plusieurs fichiers de mise en œuvre. Cependant, le premier lienait sans aucun problème (car il n'y a bien aucun problème avec num_sociiodem_files déclaration). Pourquoi?

La raison en est que votre objet num_sociiodem_files est déclaré const . Dans C ++, des objets Constons ont lien interne par défaut, ce qui signifie qu'ils ne causent pas de problèmes de liaison, même s'ils sont définis dans plusieurs fichiers de mise en œuvre. En d'autres termes, en C ++ votre num_sociodem_files est équivalent à xxx

C'est pourquoi il ne conduit à aucun problème de liaison. < P> En même temps, votre sociodem_filenames n'est pas déclaré constant, c'est pourquoi il obtient lien externe par défaut et conduit éventuellement à des erreurs de liaison. Mais si vous déclarez votre sociodem_filenames comme const aussi, le problème disparaîtra xxx

note où le supplément < Code> Const est placé dans la déclaration. Si vous ajoutez simplement cet extra const et laissez tout le reste tel qu'il est (c.-à-d. Garder la définition si sociodem_filenames dans le fichier d'en-tête), le linker ne signalera pas l'erreur même si vous Indiquez votre fichier d'en-tête en plusieurs unités de traduction.

Ce n'est pas une approche recommandée cependant, car de cette façon, vous donnerez votre sociodem_filenames liaison interne et finissez avec une copie autonome de < Code> SocioDem_Filenames Array dans chaque unité de traduction - quelque chose qui pourrait fonctionner bien mais il est toujours très peu de sens. Donc, pour votre tableau, il est normalement préférable d'utiliser l'approche extern recommandée dans d'autres réponses.

Toutefois, note que vous ne devriez pas normalement le faire pour num_sociiodem_files Déclaration !!! C'est bien tel qu'il est, défini dans le fichier d'en-tête. Sauf si vous essayez de faire quelque chose d'inhabituel, les constantes scalaires devraient normalement être définies avec Initializer dans les fichiers d'en-tête - de cette façon, ils peuvent être considérés comme des constantes de compilation dans toutes les unités de traduction, ce qui est un assez précieux chose à avoir. Ainsi, méfiez-vous de l'étrange conseil présent dans d'autres réponses pour déplacer la définition de num_sociodem_files dans .cpp fichier également - cela n'a aucun sens et est une chose totalement erronée faire.


1 commentaires

Wow merci. Cela explique beaucoup. Cela a résolu à peu près le même problème pour moi.