Problem beim Freigeben von Speicher
-
Ich wollte mir eine Klasse schreiben, die für mich die Objektserialisierung übernimmt. Bisher habe ich in etwa folgendes:
struct ObjectData { virtual ~ObjectData() { }; }; class Object { protected: ObjectData *pData; void read(std::ifstream&); void write(std::ofstream&); // ... };
Möchte ich nun beliebige Objekte serialisieren, so geht das wie folgt. Ich leite das "neue" Objekt von der Klasse Object ab und allokiere im Konstruktor Speicher für pData. Das ganze sieht dann in etwa so aus:
struct WhateverObjectData : public ObjectData { // hier Daten einfügen, z.B... int whatever[100]; char whatever[40]; // ... }; WhateverObject::WhateverObject { pData = new WhateverObjectData; // ... }
Das Serialisieren der Objekte (z.B. in Dateien) funktioniert wunderbar, auch das Einlesen klappt!!
Komisch ist aber, dass es immer zu einem Programmabsturz kommt (segfault), wenn ich den in pData allokierten Speicher freigeben will.
Hat jemand eine Idee?
-
desperato schrieb:
Komisch ist aber, dass es immer zu einem Programmabsturz kommt (segfault), wenn ich den in pData allokierten Speicher freigeben will.
Und an welcher Stelle im Code passiert das?
-
Hier noch ein wenig Pseudo-Code:
WhateverObject obj1; WhateverObject obj2; obj2.manipulateData(); obj2.write(objectfile); obj1.read(objectfile); // Bis hier hin alles ok! obj1 enthält die Daten, die ehemals obj2 hatte!
Sobald aber der Destruktor von obj1 aufgerufen wird, gibt es ein segfault. Der Destruktor von obj2 funktioniert ohne Probleme.
Kann es sein, dass ich beim Einlesen in obj1 irgendwie Speicher überschreibe? Und ich das eben erst merke, wenn beim Freigeben eine Zugriffsverletzung auftritt?
-
desperato schrieb:
Kann es sein, dass ich beim Einlesen in obj1 irgendwie Speicher überschreibe? Und ich das eben erst merke, wenn beim Freigeben eine Zugriffsverletzung auftritt?
Klar kann das sein. Kann auch sein, das es an etwas Anderem liegt.
Da du dich aber standhaft weigerst, zu verraten, was in den Funktionen
WhateverObject::read,
WhateverObject::write,und vor allem
WhateverObject::~WhateverObject
passiert, bleibt die Antwort so ungenau wie die Frage. Dein Pseudocode hilft jedenfalls nicht weiter.
-
Sorry, ich wollte nich unhöflich erscheinen. Also in den Funktionen passiert folgendes:
// READ-FUNKTION void Object::read(std::ifstream &infile) { infile.read((char*)&pData, sizeof(pData)); } // WRITE-FUNKTION void Object::write(std::ofstream &outfile) { outfile.write((char*)&pData, sizeof(pData)); } // RELVANTER DESTRUKTOR WhateverObject::~WhateverObject() { if(pData) delete pData; }
Mehr passiert da echt nicht!
Und Speicher ist allokiert, d.h. pData zeigt auf jeden Fall auf einen gültigen Bereich.
Hm... bin ich so dumm oder sehe ich den Wald vor lauter Bäumen nicht?!
-
desperato schrieb:
Sorry, ich wollte nich unhöflich erscheinen.
Du warst nicht unhöflich. Du hast nur zuwenige Informationen geliefert. Jetzt ist's besser.
infile.read((char*)&pData, sizeof(pData));
Ganz schlecht. Erstens liest du direkt in den Zeiger, nicht in den Speicherbereich, auf den der Zeiger zeigt. Das & vor pData muss weg.
Zweitens ist pData ein Zeiger, und sizeof(pData) damit die Größe eines Zeigers, auf heute üblichen Plattformen also 4.Das gleiche gilt für write.
if(pData) delete pData;
Das if kannst du dir sparen, ein delete auf einen Nullzeiger tut nichts.
-
Vielen Dank für die Hilfe!
Also es war wirklich das & vor dem Zeiger, das den Crash verursacht hat. Ist ja eigentlich auch logisch...
- Aber das kommt davon, wenn man einfach schnell drauf loshackt...