8
votes

Crash destructeur

Je travaille sur une application Win32 C ++ dans Visual Studio.

Dans l'un des fichiers source, j'ai un objet global comme ci-dessous. P>

struct Source
{

};

class TestClass
{
  list<Source> sourceList;
    public:
         TestClass() {}
        ~TestClass() {}
};


5 commentaires

Utilisez quatre espaces pour indenter le code et aucun pour le texte normal.


Avez-vous construit l'EXE et la DLL avec le même runtime C ++?


Oui j'ai construit les deux avec Visual Studio. Seul le type de configuration est différent. L'un est EXE et d'autres sont la configuration DLL dans les paramètres du projet.


Comment reliez-vous votre DLL à EXE? par liaison statique conventionnelle (utilisation de .lib)


Crash est résolu en utilisant la même bibliothèque d'exécution dans EXE et DLL. Merci à tous de m'aider.


6 Réponses :


1
votes

Il s'écrase dans le destructeur, une exception est lancée à partir du destructeur qui appelait terminer et écraser votre application. Exceptions non capturées

Il y a deux situations dans lesquelles un destructeur est appelé. Le premier est quand un objet est détruit dans des conditions "normales", par exemple, lorsqu'elle est hors de portée ou est explicitement supprimée. La seconde est quand un objet est détruit par le mécanisme de manipulation d'exception lors de la partie déroulante de la pile de propagation d'exception. Vous devez écrire vos destructeurs sous l'hypothèse conservatrice qu'une exception est active, car si le contrôle laisse un destructeur en raison d'une exception, tandis qu'une autre exception est active, C ++ appelle la fonction de terminaison


3 commentaires

L'objet global est construit avant que le principal () soit appelé. Je pense donc que sa destruction se passe après les sorties principales (). Ce temps, la liste Sourcelist Tête que STL utilise en interne, n'est pas valide au moment de la libération. Par conséquent, CrtisvalidHeappointer échoue.


La question est la suivante: pourquoi la tête de Sourcelist est-elle invalide? Si votre EXE & DLL est correctement construit avec des roulements compatibles, ce code devrait fonctionner correctement. Le runtime nettoyera les objets globaux avant que le tas ne soit libéré.


Crash est résolu en utilisant la même bibliothèque d'exécution dans EXE et DLL. Merci à tous de m'aider.



1
votes

Les objets globaux sont initialisés et détruits par le temps d'exécution C. Ils sont initialisés avant principal est appelé et détruit après son retour.

L'erreur est probablement causée par quelque chose qui est accessible à partir de votre destructeur destructeur (ou indirectement à partir d'une source source destructeur). Le code Destructor accède à la mémoire non valide (ou à la mémoire déjà libérée).

L'ordre d'initialisation et de destruction des variables globales n'est pas défini et est fréquemment une source d'erreurs sur la résiliation des applications. S'il y a d'autres globaux qui pourraient nettoyer ou modifier des ressources référencées par testclass, cela pourrait être le coupable.


2 commentaires

Je n'ai ajouté aucun nœud au Sourcelist (liste ). La liste est vide au moment de l'appel destructeurs. Mais toujours, la liste STL aura un pointeur de tête caché en interne. En essayant de libérer cela, sa crash.


Quel (s) CRT (s) construisez-vous l'EXE et la DLL?



4
votes

Assurez-vous de construire Bot l'EXE et la DLL avec le même runtime, de préférence avec le temps d'exécution dynamique.


1 commentaires

Crash est résolu en utilisant la même bibliothèque d'exécution dans EXE et DLL. Merci à tous de m'aider.



0
votes

sont la DLL et l'exe construit à l'aide du même alignement (Pack Pragma)?


0 commentaires

9
votes

Votre problème est que les paramètres de compilation / liaison différents entre les .exe et .dll provoquent efficacement le fichier .dll et .exe d'utiliser différentes implémentations de la bibliothèque standard:

  • Vous devez utiliser les mêmes drapeaux de préprocesseur * pour créer à la fois le .exe et le .dll, sinon chaque binaire compilera avec des implémentations subtilement différentes.
  • Vous devez relier à la fois la .exe et le .dll vers le temps d'exécution dynamique. Les fichiers binaires liés de manière statique au runtime obtiennent leur propre tas - et vous finissez par allouer sur un tas et essayant de libérer sur un autre.

    Pour résoudre ce problème, allez à Projet> Propriétés> Propriétés de configuration> C / C ++> Génération de code et modifier l'option de la bibliothèque d'exécution en DLL de débogage multi-threadé (/ MDD) . Vous devez le faire pour le projet .exe et le projet .dll.

    AS de Visual Studio 2010, certaines de ces types d'erreurs seront détectées à l'heure de liaison utilisant # pragma détecte_mismatch .

    * pour tous les drapeaux de préprocesseur ayant des effets de la mise en œuvre de la bibliothèque standard


1 commentaires

+1 de moi pour cette réponse complète. @ bjskishore123: Veuillez lire le FAQ . Vous êtes encouragé à accepter la réponse que vous vous sentez la plus aidée à résoudre votre problème.



0
votes

Essayez de rendre votre constructeur et destructeur non intégré, cela peut aider. Si CORTOR et DTOR ne sont pas en ligne, les deux seront générés au nom de la DLL, de sorte que la construction et la destruction de la liste <> seront exécutées avec la même bibliothèque d'exécution. Généralement, essayez d'éviter de passer des objcts opaques stl sur les limites de la DLL. Il est préférable de les incapable comme des membres du privatterie dans vos propres classes et de fournir des méthodes non inlinées pour manipuler un tel membre


0 commentaires