9
votes

Fichiers d'objet C ++ modèles

permet de dire que j'ai deux fichiers .CPP, fichier1.cpp et fichier2.cpp, qui utilisent std :: vecteur . Supposons que FILE1.CPP ait un Int Main (VOID) . Si j'ai compilé à la fois dans File1.o et File2.o et liez les deux fichiers d'objets dans un binaire ELF que je peux exécuter. Je compile une machine à linux Ubuntu 32 bits.

Ma question concerne la manière dont le compilateur et la liante mettent ensemble les symboles du STD :: Vector:

  • Lorsque le lieur fait mon binaire final, existe-t-il une duplication de code? Est-ce que la lieur a un ensemble de code "modèles" pour le code dans F1.o qui utilise std :: vecteur et un autre ensemble de std :: vecteur code pour le code qui comprend F2.O?

    J'ai essayé cela pour moi-même (j'ai utilisé g ++ -g ) et j'ai examiné mon démontage exécutable final, et j'ai trouvé les étiquettes générées pour le constructeur de vecteur et d'autres méthodes étaient apparemment aléatoires, bien que la Le code de F1.O semblait avoir appelé le même constructeur que le code de F2.o. Je ne pouvais pas être sûr, cependant.

    Si la lieur empêche la duplication de code, comment le fait-il? Doit-il "savoir" quels modèles sont? Est-ce que cela empêche toujours la duplication de code concernant plusieurs utilisations du même code modèles sur plusieurs fichiers d'objet?


0 commentaires

3 Réponses :


10
votes

Il sait ce que les modèles sont passés par Nom Mangling . Le type de l'objet est codé par le compilateur sous son nom et permet au linker de filtrer les implémentations en double du même modèle.

Ceci est fait lors de la liaison et non de la compilation, car chaque fichier .O peut être lié à tout ce qui ne peut donc pas être dépouillé de quelque chose qui pourrait être nécessaire plus tard. Seul la liaison peut décider quel code est inutilisé, quel modèle est en double, etc. Ceci est effectué en utilisant " symboles faibles " Dans la liste des symboles de l'objet: les symboles que le lieur peut supprimer s'ils apparaissent plusieurs fois (par opposition à d'autres symboles, tels que les fonctions définies par l'utilisateur, qui ne peuvent pas être supprimées si dupliquer et provoquer une erreur de liaison).


7 commentaires

Cela ne traite pas la majeure partie de la question de l'OP. C'est vrai, mais ce n'est pas particulièrement pertinent pour ce qui est demandé ici.


@ Templatetypedef - Je prie de différer. Si la lieur empêche la duplication de code, comment le fait-il? Doit-il "savoir" quels modèles sont? Le linker sait à travers le nom Mangling. Code en ligne - est dupliqué, la lieur n'a rien à voir avec cela.


@ Littleadv- Vous êtes absolument correct, mais votre réponse telle qu'elle ne traite pas pourquoi la liaison utilise Name Mangling, comment les noms mutilés pour les fonctions de modèle diffèrent des fonctions régulières, comment le linker décide des versions à choisir, etc. Je suis Ne pas essayer de dire que ceci est hors topique ou incorrect, mais si vous ne saviez que si vous ne connaissiez pas la réponse à la question, je ne pense pas que cette réponse sera utile.


@Templatetypedef J'ai supposé avoir cliqué sur le lien et lire un peu plus, mais ajouté quelques mots supplémentaires pour les pédants.


Pourquoi le linker ne se plaignait-il pas d'un symbole en double ou de quelque chose de similaire? Il semble que mes fichiers .O ont une partie du code de vecteur défini dans une section .text.mangled_name . Est la raison pour laquelle ils sont dans une section différente?


@Chris - parce qu'il l'identifie comme un modèle et supprime les duplicats. Ça s'appelle "symboles faibles". Ajouté à la réponse


@littleadv ah, oui, je vois les symboles avec l'attribut faible de la sortie binaire. Merci!



0
votes

Techniquement due à la "règle d'une définition", il n'y a qu'un seul std :: vecteur et donc le code doit être lié ensemble. Ce qui peut arriver, c'est que certains codes sont inlinés, ce qui accélérerait le temps d'exécution mais pourrait produire plus de code.

Si vous aviez un fichier en utilisant std :: vecteur et une autre utilisation std :: vecteur vous auriez 2 classes et potentiellement lots de code dupliqué.

Bien sûr, les écrivains du vecteur peuvent utiliser un code commun pour certaines situations, par exemple des types de pod qui supprime la duplication.


3 commentaires

Je ne suis pas inquiet de la duplication STD :: vecteur et std :: vecteur . Quelle est exactement la "règle d'une définition?" La définition de std :: vecteur créée à la date de compilation pour f1.o et f2.o?


La "règle d'une définition" est par fichier objet, entre fichiers d'objets distincts, vous obtiendrez deux instances différentes de vecteur si elles l'utilisent les deux. Ce qui est inliné - sera dupliqué, ce qui n'est pas - géré par la liaison.


En bref, la règle d'une définition indique que si des instances de modèles identiques apparaissent dans plusieurs unités de compilation, cela ne compte toujours que pour le compilateur comme une seule définition de cette instance de modèle. Fondamentalement, C ++ comporte cette étape supplémentaire entre la compilation et le code d'objet liant dans le but spécifique de supprimer ces copies supplémentaires du code de modèle.



4
votes

Votre question est indiquée Verbatim dans la section d'ouverture de cette documentation:

http://gcc.gnu.org/onlineCs/gcc/template- Instanciation.html


0 commentaires