Zeiger doppelt gelöscht
-
Hallo Zusammen,
Ich befasse mich noch nicht lange mit C++ und habe ein Grundlegendes Zeiger Problem.
Es besteht folgende Situation.
Ich habe 2 Klassen. In Klasse 1 Initialisiere ich einen buffer, danach wird ein IP Paket in diesen buffer geschrieben. Danach rufe ich auf der zweiten Klasse die Funktion decode auf und übergebe diesen buffer der Funktion. Diese Funktion casted diesen buffer auf zwei member pointers die die struktur abbilden des Pakets. Wird die While-Schleifen Bedingung in Klasse 1 auf False gesetzt lösche ich den buffer. Danach wird der Destruktor der Klasse 2 aufgerufen. Logischer weise muss ich hier meine allokierten speicher wieder freigeben. Das Problem ist nun das ja sowohl der buffer wie auch meine beiden member zeiger auf den selber speicher bereich zeigen. Lösche ich nun also den buffer dann ist der speicher von den member zeiger bereits freigegeben jedoch zeigen diese immer noch auf diesen speicher bereich. Nochmaliges löschen ergibt im Debug modus eine Assertmeldung.Wie löst man dieses Problem? Ich habe mich ein bisschen mit Smart Pointer befasst wie auch Referenzzählung. Ist dies die einzige Methode?
Klasse 1:
char* buffer = new char[ BUFFSIZE ]; while( bedingung ) { // Hier empfägt das Programm etwas und schreibt es in den buffer klasse2->decode( buffer ); } delete [] buffer; buffer = 0;Klasse 2:
// Members IPV4* IpHdr; UDP* UdpHdr; // Konstruktor Klasse2( void ) : IpHdr( 0 ), UdpHdr( 0 ) { // Leer } // Destruktor ~Klasse2() { if( IpHdr ) { delete IpHdr; IpHdr = 0; } if( UdpHdr ) { delete UdpHdr; UdpHdr = 0; } } decode( char* p_buffer ) { IpHdr = reinterpret_cast< IPV4 * >( p_buffer ); p_buffer = p_buffer + IpHdrLength; UdpHdr = reinterpret_cast< UDP * >( p_buffer); }
-
zunächst mal passt delete nicht zu new[].
mögliche lösungen für die fragestellung:
1. Klasse2::decode macht eine deep copy und verwaltet es dann selbst
2. du löschst den buffer ganz einfach nicht selbst sondern überlässt es dem destruktor
3. du löschst den buffer im destruktor nicht, ist ja nicht die aufgabe von Klasse2aber allgemein sind wir hier eigentlich in c++, arbeite also lieber mit containern und iteratoren
-
Welche der beiden Klassen besitzt nun diesen Buffer? Diese solle übrigens nicht mit rohem
new/delete(letzteres schon gar nicht) arbeiten, sondern mitstd::string, welches du sicherlich schon kennst. Von diesem kannst du einfach die Adresse des ersten Zeichens nehmen, dann hast du schon einen nullterminierten, beschreibbaren String.Natürlich kannst du den String aber auch einfach kopieren, das ist eine der Vorteile beim
std::string- und lohnt sich hier, da es nicht weiter darauf ankommt, dass beide Klasse denselben String bearbeiten. Natürlich nur wenn der String nicht sehr groß ist, und eine solche Kopie performancetechnisch verkraftbar.Ich wundere mich allerdings, wieso du in jedem Schleifendurchlauf durch
decodedie in Klasse 2 befindlichen Zeiger setzen lässt.if( IpHdr ) { delete IpHdr;Die Abfrage ist völlig überflüssig:
deletenimmt auch Nullzeiger.