Probleme mit vector
-
Hallo zusammen... ich lege in einem Vector Pointer auf Objekte ab, die ich mit new erzeuge
CKlasse* pTest = new CKlasse(); m_Vector->insert(m_Vector->end(), pTest);Nun arbeite ich ein bischen und wenn ich nun die erzeugten Objekte wieder freigeben möchte mit
CKlasse* pElement; while(pVector->size() > 0) { pElement = pVector->back(); pVector->pop_back(); delete pElement; } pVector->clear();Bekomme ich schon beim ersten Aufruf von delete den folgenden Fehler:
HEAP[Test.exe]: Invalid Address specified to RtlValidateHeap( 00350000, 00D8774C )
Wieso?!
Ich benutze Microsoft Visual Studio 2005... und die STL die dort integriert ist

Danke für Antworten!
-
Ist es unbedingt nötig, deine Objekte mit new anzulegen? Du kannst dir die Arbeit deutlich vereinfachen, indem du die Objekte direkt in den vector<> packst (anstatt Pointer zu verwenden).
Ansonsten: Der Fehler sieht danach aus, als ob du entweder deinen Heap demoliert (durch Bereichsüberschreitungen o.ä.) oder eins der vector-Elemente schon vor dieser Aufräumschleife freigegeben hast. Aus deinem Code-Schnipsel kann man leider nicht erkennen, wo der Fehler liegt.
-
Also wenn der Heap doch defekt wäre würden doch Zeiger irgendwo hinzeigen die es nicht gibt oder?
Also wenn ich das delete weglasse und eine Ausgabe aufrufe der Art:
CKlasse* pElement; while(pVector->size() > 0) { pElement = pVector->back(); pVector->pop_back(); TRACE("%s\n", pElement->Name()); } pVector->clear();Bekomme ich die wunderbare Ausgabe aller Namen... und zwar von jedem Objekt das ich angelegt habe.
Wenn ich keine Zeiger verwende sondern direkt die Objekte in meinen vector aufnehme... dann die Funktion verlasse werden die Objekte doch zerstört oder?
-
Also wenn der Heap doch defekt wäre würden doch Zeiger irgendwo hinzeigen die es nicht gibt oder?
Also wenn ich das delete weglasse und eine Ausgabe aufrufe der Art:
CKlasse* pElement; while(pVector->size() > 0) { pElement = pVector->back(); pVector->pop_back(); TRACE("%s\n", pElement->Name()); } pVector->clear();Bekomme ich die wunderbare Ausgabe aller Namen... und zwar von jedem Objekt das ich angelegt habe. Deswegen müßten doch die Objekte auf dem Heap ok sein...

-
Meyer123 schrieb:
Also wenn der Heap doch defekt wäre würden doch Zeiger irgendwo hinzeigen die es nicht gibt oder?
Das ist ja das unangenehme am "undefined behaviour" - du kannst dir nie sicher sein, was dein Programm macht. Und wenn der Heap kaputt ist, kann das auch nur die Kontroll-Informationen betreffen, die delete zum Freigeben deiner Objekte benötigt.
Wenn ich keine Zeiger verwende sondern direkt die Objekte in meinen vector aufnehme... dann die Funktion verlasse werden die Objekte doch zerstört oder?
Wenn die Objekte direkt im vector stehen, werden sie von dessen Destruktor automatisch freigegeben - aber du kannst den vector natürlich auch zwischen verschiedenen Funktionen weiterreichen (genauso wie du den Zeiger-vector rumreichen kannst) - dann überleben die Objekte auch so lange, wie du sie benötigst.
(beim Zeiger-Vector mußt du dich selber darum kümmern, daß vor dem Dtor-Aufruf alle Elemente freigegeben werden - andernfalls hast du ein Speicherleck)
-
Wenn die Objekte direkt im vector stehen, werden sie von dessen Destruktor automatisch freigegeben - aber du kannst den vector natürlich auch zwischen verschiedenen Funktionen weiterreichen (genauso wie du den Zeiger-vector rumreichen kannst) - dann überleben die Objekte auch so lange, wie du sie benötigst.
Erstmal danke für die Info :)...
Ich hab jetzt doch mehr herausgefunden :)... Also ich hab jetzt mal testweise einfach den vector weggelassen und folgendes festgestellt

CKlasse*pTest = new CKlasse(); TRACE("1. %d\n", (IKlasse*) pTest); TRACE("2. %d\n", (CKlasse*) pTest);Die Ausgabe ergibt folgendes:
1. 3512428
2. 3512344CKlasse erbt von der abstrakten IKlasse... von CKlasse muss jedoch auf jedenfall der Destruktor aufgerufen werden...
Wenn ich nun delete (IKlasse*) pTest tritt der Fehler mit dem HEAP auf... wenn ich delete (CKlasse*) pTest aufrufe nicht... das Problem ist ich möchte in dem Vector viele IKlassen speichern (Verallgemeinerung)... CKlasse ist ja nur eine Konkretisierung... wieso tritt den dieser HEAP-Fehler auf... und wieso haben die beiden Zeiger unterschiedliche Adressen :(...
-
Die Adressen sind unterschiedlich, weil du Merhfachvererbung verwendest - die Klasse wird aus ihren Elternklassen zusammengesetzt, indem diese nach bestimmten Gesichtspunkten hintereinandergeschrieben werden (die Differenz zwischen "Startpunkt der Kindklasse" und "Startpunkt der Elternklasse" ist idR konstant, so daß der Compiler bei Methodenaufrufen oder Typ-Casts den Offset draufrechnen kann).
Das Problem mit dem zerstörten Heap lässt sich auch auf diese Unterschiede zurückführen - der Dtor von IKlasse weiß nicht, daß er eigentlich nur ein kleiner Teil eines größeren CKlasse-Objekts ist, also löscht er nur seine eigenen Daten - und delete versucht auch nur, den IKlasse-Teil deines Objekts zu zerlegen. Und das macht Probleme, weil die Adresse des IKlasse-Teils nicht von new stammt (new hat die Adresse des kompletten Objekts zurückgeliefert).
Die Lösung für dieses Dilemma nennt sich "virtueller Destruktor" - indem du den Dtor der Elternklasse 'virtual' definierst, wird zur Laufzeit der richtige Dtor für dein Objekt aufgerufen, egal über welchen Zeigertyp es zerstört werden soll.
-
Was würde ich nur ohen dieses Forum tuen... und vorallem ohne dich CStoll...
Hät ich aber auch selber dran denken können... dieses kleine Wort :(...
Ich danke dir auf jedenfall!!!
TAUSEND DANK!!