Question

J'ai une classe avec une méthode statique qui ressemble à peu près à:

class X {
    static float getFloat(MyBase& obj) {
        return obj.value();  // MyBase::value() is virtual
    }
};

Je l'appelle avec une instance de MyDerived dans laquelle la sous-classe MyBase est créée:

MyDerived d;
float f = X::getFloat(d);

Si je lie le fichier obj contenant X à mon exécutable, tout fonctionne comme prévu. Si je prévois avoir 3.14, je l’ai.

Si je crée un fichier .lib contenant le fichier X.obj et un lien dans le fichier .lib, il se rompt. Lorsque j'appelle getFloat (), il renvoie -1. # IND00 . Est-ce une sorte de valeur sentinelle qui devrait me dire ce qui ne va pas ici?

Quelque chose de différent lorsque vous créez un lien dans une bibliothèque plutôt que directement dans un obj?

Je ne reçois aucun avertissement ni aucune erreur du compilateur.

Modifier:
J'utilise Visual Studio 2005 sur Windows XP Pro SP3. Pour m'assurer que je ne liais pas d'anciens fichiers, j'ai cloné la méthode value () dans une nouvelle méthode value2 () et l'ai appelée à la place. Le comportement était le même.

Modifier n ° 2:
Donc, si je trace dans l'appel avec mon débogueur, je constate que cela ne va pas du tout dans ma méthode value (). Au lieu de cela, il entre dans une méthode différente (non liée). Cela me fait penser que ma table virtuelle est corrompue. Je pense que le comportement que je vois doit être un effet secondaire d'un autre problème.

Résolu! (merci à Vlad)
Il est apparu que je violais la règle de définition unique (ODR), bien que cela ne ressorte pas du code que j'ai publié. This est un excellent article des gars de Visual C ++ qui explique le problème et fournit un moyen de le localiser. Le drapeau du compilateur / d1reportSingleClassLayout est un outil d’apprentissage fantastique.

Lorsque j'ai vidé la mise en page de ma classe pour MyBase et MyDerived dans les deux projets différents, j'ai constaté des différences entre le code appelant et le code de la bibliothèque. Il se trouve que j'avais dans mes fichiers d'en-tête des blocs #ifdef et que l'instruction #define correspondante se trouvait dans l'en-tête précompilé du projet principal, mais pas dans le sous-projet (la bibliothèque ). Ai-je déjà mentionné à quel point les macros du préprocesseur sont diaboliques?

Quoi qu'il en soit, je ne fais que publier ce contenu, car cela pourrait être utile à quelqu'un d'autre. Cette question m'a également été très utile.

Était-ce utile?

La solution

Ce problème se produira lorsque la bibliothèque et l'exécutable auront été compilés avec différentes définitions de la classe MyDerived (c'est-à-dire différentes versions du .h / .hh / .hpp fichier déclarant MyDerived . Nettoyez et reconstruisez complètement vos projets. Sinon, différentes options du compilateur pourrait être responsable, bien que cela soit peu probable.

Si le problème persiste après avoir tout reconstruit à partir de zéro, résolvez-le en instanciant un objet fictif MyDerived dans getFloat , dans la bibliothèque. Utilisez le débogueur pour comparer la vtable du dummy MyDerived (instancié dans la bibliothèque) et la vtable du MyDerived référence d'objet passée en paramètre (instanciée dans l'exécutable.) Quelque chose devrait se passer immédiatement aux yeux.

Autres conseils

Etant donné qu'une lib est simplement un conteneur, si vous liez le même fichier .obj dans les deux cas, alors comme le dit Brian, ils ne devraient pas (ne peuvent pas?) faire la différence.

Une chose à surveiller est que si vous modifiez la définition de MyBase, vous devez évidemment recompiler à la fois la bibliothèque et le code qui l’utilise. Par exemple, si vous avez ajouté une nouvelle méthode virtuelle à MyBase avant la méthode value, cela gâcherait la bibliothèque car le décalage de valeur de la table virtuelle serait différent.

Il ne devrait y avoir aucune différence. Assurez-vous simplement que les fichiers .h que vous incluez correspondent à la .lib vers laquelle vous créez un lien. Je soupçonne que vous pouvez créer un lien vers un ancien fichier .lib.

Si vous utilisez visual studio, au lieu de spécifier explicitement le fichier .lib, cliquez simplement sur le projet avec le bouton droit de la souris et définissez les dépendances du projet .lib. De cette façon, vous serez sûr qu'il utilise le bon fichier .lib.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top