Debug Assertion failed bei delete
-
Hi,
ich hab meine Klassen jetzt schon extrem abgespeckt, aber ich hab hier ein mysteriöses Problem:
class CModel { public: DLL CModel(); DLL virtual ~CModel(); }; class CMD2Model : public CModel { public: DLL CMD2Model(); DLL virtual ~CMD2Model(); }; CModel::CModel() { ENGINE_LOG("CModel-Konstruktor\n"); } CModel::~CModel() { ENGINE_LOG("CModel-Destruktor\n"); // ... } CMD2Model::CMD2Model() : CModel() { ENGINE_LOG("CMD2Model-Konstruktor\n"); } CMD2Model::~CMD2Model() { ENGINE_LOG("CMD2Model-Destruktor\n"); // ... }
Mein Hauptcode sieht so aus:
CModel *pModel; pModel = new CMD2Model(); delete pModel;
Beim Delete krieg ich eine Debug Assertion Failed-Dialogbox beim Ausführen und wenn ich das ganze im Debugger ausführe, krieg ich eine Meldung "benutzerdefinierter Haltepunkt aufgerufen in ..." und sehe nur Assemblercode.
EDIT: Auskommentierte Anwendungen aus dem Code oben entfernt.
Noch eine Ergänzung: Von den ENGINE_LOG()-Makros stehen alle im Log und ohne die gehts logischerweise auch net (nicht das jemand meint, an denen würde es liegen).ChrisM
[ Dieser Beitrag wurde am 15.12.2002 um 18:54 Uhr von ChrisM editiert. ]
-
Hab den Fehler genauer eingegrenzt. Hab jetzt nur noch diese Klasse:
class CMD2Model { public: DLL CMD2Model(); DLL virtual ~CMD2Model(); };
Im Hauptprogramm erzeuge ich eine Instanz von CMD2Model mit new auf dem Heap und zerstöre sie wieder mit delete (und kriege die Debug Assertion Failed
).
Lasse ich aber das virtual beim Destruktor weg, gehts einwandfrei!Woran liegt das?
ChrisM
[ Dieser Beitrag wurde am 15.12.2002 um 20:00 Uhr von ChrisM editiert. ]
-
Hi,
hab den Fehler mal in einem kleinen Demoprojekt isoliert (insgesamt ~20 Zeilen):
www.chrismandery.de/FehlerDemo.zipChrisM
-
So wie es aussieht hat das doch was mit der DLL zu tun. Wenn man den Code in die Anwendung übernimmt kommt der Fehler nicht. Deswegen gehört das hier garnicht hin.
-
Naja, ich verwend aber an anderer Stelle in meiner DLL einen virtuellen Destruktor und dort gehts.
Aber von mir raus, kann man das hier gerne ins VC-Forum verschieben.
ChrisM
-
Hi,
linke mal gegen die DLL-Version der Laufzeitbibliothek, dann müsste es eigentlich funktionieren.
-
Hmm... versteh ich nicht.
Vielleicht kann ja mal jemand meinen Quellcode ( www.chrismandery.de/FehlerDemo.zip ) runterladen und mir sagen, warum der nicht geht und was ich machen kann (außer Destruktor nicht virtuell machen
).
ChrisM
-
Wie importierst du denn Klassen?
class __declspec(dllimport) CTestklasse { public: CTestklasse(); virtual ~CTestklasse(); };
-
Nein, ich importiere jede Funktion einzeln, also __declspec(dllimport) für jede Funktion.
In meinem kleinen Demoprojekt hab ich das vergessen, aber ich glaub, der Linker merkt das automatisch, wenn er importieren soll ...Naja, egal, in meinem "richtigen" Projekt ist der Destruktor so deklariert:
class CMD2Model { public: DLL CMD2Model(); DLL virtual ~CMD2Model(); };
Lasse ich das virtual beim Destruktor weg, gehts ohne Probleme. (in der Originalfassung, die natürlich auch net geht, erbt CMD2Model noch von CModel)
ChrisM
[ Dieser Beitrag wurde am 16.12.2002 um 13:34 Uhr von ChrisM editiert. ]
-
Wieso egal? Probiers doch mal aus.
Bei mir geht es so.
-
Ich post jetzt mal den "echten" Code:
#ifdef ENGINE_DLLEXPORT #define DLL __declspec(dllexport) #else #define DLL __declspec(dllimport) #endif class CMD2Model { public: DLL CMD2Model(); DLL virtual ~CMD2Model(); // <- ohne virtual gehts!! }; CMD2Model::CMD2Model() { ENGINE_LOG("CMD2Model-Konstruktor\n"); } CMD2Model::~CMD2Model() { // Dieser Text steht noch im Log, d.h. der Fehler kommt erst danach! ENGINE_LOG("CMD2Model-Destruktor\n"); }
ChrisM
-
Hi Chris,
im Moment linkst du gegen die statische Version der C/C++ Laufzeitbibliothek. Das heisst das jedes Modul sozusagen seinen eigenen Heap hat und es deshalb zu Chaos kommt.
Deshalb meinte ich du solltest gegen die DLL-Version der Laufzeitbibliothek linken. Dann existiert nämlich nur ein gemeinsamer Heap-Manager. Ich hatte dein Projekt gestern schon runtergeladen, die Änderungen vorgenommen und dannach hatte es funktioniert. Die Einstellung findest du unter:Projekt | Einstellungen | C-C++ | Codeerstellung | Laufzeitbibliothek
Mach dort mal folgende Einstellungen:
EXE Debug -> Multithreaded-Debug-DLL
DLL Debug -> Multithreaded-Debug-DLLEXE Release -> Multithreaded DLL
DLL Release -> Multithreaded DLLWichtig ist das EXE und DLL gegen die gleiche Laufzeitbibliothek linken.
-
Cooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooool!
ES GEHT!!!!!!! (und ich hab gedacht, dass Trolle net nützlich sind
)
Aber hab ich dadurch jetzt Geschwindigkeitsverlust bekommen und wieso gehts bei manchen virtuellen Destruktoren? Kann es sein, dass es dann geht, wenn der Delete-Aufruf beim "normalen" Linken im gleichen Modul erfolgt? Und jetzt darf es überall deleten?
Danke!
ChrisM