web-dev-qa-db-fra.com

Qu'est-ce qu'une "fonction clé" C ++ telle que décrite par gold?

Veuillez ne pas répondre à la question "comment résoudre ce message d'erreur?"

Dans le message d'erreur fourni par gold:

/usr/bin/ld.gold: the vtable symbol may be undefined
because the class is missing its key function

Qu'est-ce qu'un key function? J'y trouve référence dans la page de manuel GCC pour les attributs de fonction sous la section dllimport. Le texte pertinent se lit comme suit:

Sur la cible SH Symbian OS, l'attribut dllimport a également un autre effet (sic): il peut entraîner l'exportation des informations de type vtable et d'exécution pour une classe. Cela se produit lorsque la classe a un constructeur dllimport'ed ou une fonction virtuelle non en ligne, non pure et, pour l'une ou l'autre de ces deux conditions, la classe a également un constructeur ou destructeur en ligne et a une fonction clé qui est définie dans le unité de traduction actuelle.

J'en retire qu'il existe une fonction distincte des constructeurs ou des destructeurs, requise dans certaines conditions, lors de l'utilisation de l'attribut dllimport, sur Symbian OS. Intéressant, mais je compile pour Linux sur Linux, et grep -r dllimport ne révèle rien. Ce paragraphe ne s'applique donc pas.

(FWIW, le problème provient (dans ce cas) d'un destructeur indéfini mais la documentation et la sortie de l'éditeur de liens se donnent beaucoup de mal pour distinguer un " fonction clé "d'un destructeur. Pour les autres types de symboles manquants, l'éditeur de liens épelle le nom du symbole manquant.)

Alors, qu'est-ce qu'un key function vraiment ?

29
Cuadue

la fonction clé est définie comme la première fonction virtuelle non intégrée déclarée dans la classe. Le wiki officiel de gcc à ce sujet est ici .

25
navylover

(déplacement/extension du commentaire)

Comme @navylover l'a expliqué, la fonction clé est la première fonction virtuelle non en ligne définie dans la classe; c'est important car il est utilisé par le compilateur comme un marqueur conventionnel pour décider dans quel TU la vtable doit être émise (car elle ne doit être émise qu'une seule fois)) - quelle que soit TU contient la définition de la fonction clé, le module objet correspondant contiendra également la vtable.

Il s'ensuit que, si aucun TU définit la fonction clé (par exemple parce que vous avez oublié de la définir), la vtable ne sera jamais émise, d'où l'erreur.

or, il essaie de vous indiquer la bonne direction: si la table est manquante, c'est probablement parce que la fonction clé est également manquante (encore une fois, soit parce que vous n'avez pas défini ou oublié de lier son module), bien qu'il ne le puisse pas être répertorié explicitement comme une référence non définie (ce qui pourrait vous mettre sur la bonne voie) car dans le reste du code personne ne l'invoque directement1, comme dans cet exemple:

struct Test {
    virtual void foo();
    virtual int bar() {
        return 0;
    }
};

int main() {
    Test t;
    t.bar();
    return 0;
}

[matteo@teolapkubuntu /tmp]$ g++ -Fuse-ld=gold keyf.cpp 
/tmp/ccduMsT3.o:keyf.cpp:function main: error: undefined reference to 'vtable for Test'
/usr/bin/ld.gold: the vtable symbol may be undefined because the class is missing its key function

Comparez cela avec GNU ld régulier, qui dit simplement

[matteo@teolapkubuntu /tmp]$ g++ keyf.cpp 
/tmp/ccUr3Xyi.o: In function `main':
keyf.cpp:(.text+0x1a): undefined reference to `vtable for Test'
collect2: error: ld returned 1 exit status

Okay, alors quoi? Ce n'est pas comme si je devais définir explicitement des vtables, donc ce n'est certainement pas évident où devrais-je commencer à chercher pour corriger ce genre d'erreur.


  1. Une telle fonction peut cependant être invoquée indirectement via un pointeur vers la classe de base, et l'éditeur de liens afficherait toujours uniquement la référence non définie à la table virtuelle et non à la fonction, comme seule référence à la fonction dans ce cas serait dans le vtable, qui est manquant.
15
Matteo Italia