Frage

Eine andere C ++ Zeiger Löschen Frage ist in dem folgenden Beispiel:

class Foo {
public:
    int *p;
    ~Foo() {
        delete p; p = NULL;
    }
};

Foo *f1 = new Foo();
Foo *f2 = new Foo();
f1->p = new int(1);
f2->p = f1->p;
delete f2; // ok
delete f1; // no error?

Warum habe ich nicht Fehler, wenn „Löschen f1“ nennen? Ich lösche nicht die gleiche Adresse (* p) zweimal?

Wenn ich direkt die Zeiger in den letzten zwei Zeilen Code löschen, ich werde Fehler.

delete f2->p; // ok
delete f1->p; // error!! *** glibc detected *** double free or corruption (fasttop) ***
War es hilfreich?

Lösung

Es ist eine sehr schlechte Sache zu tun. Jedoch C ++ wird nicht unbedingt alles hier tun. Es ist "un-defined" Verhalten. Das bedeutet nicht, es wird abstürzen, aber es wird höchstwahrscheinlich Ursache schlechte Scheiße (tm) passieren.

Edit: Außerdem in Ihrem zweiten Beispiel der Tatsache, es stürzt ab, ist nur ein Teil von „undefined“ Verhalten. Es ist nicht definiert, was die Reaktion sein wird.

Andere Tipps

  

Warum habe ich nicht Fehler, wenn „Löschen f1“ nennen? Ich lösche nicht die gleiche Adresse (* p) zweimal?

Ja haben Sie zweimal das Objekt löschen.

Doch das Ergebnis davon ist, nicht definiertes Verhalten . Die könnte Ergebnis im Laufzeitsystem der Fehler zu kontrollieren und eine Nachricht auftauchen, aber es könnte genauso gut in HD führen formatiert zu werden, böse Nasal Demons Sie rund um das Büro zur Freude der Jagd nach der Ihre Arbeitskollegen oder Sie oder Ihre Freundin schwanger zu werden. Oder dann könnte es scheint auch zu „arbeiten“, was immer das bedeutet in diesem Fall.

Vertrauen Sie mir, Sie wollen nicht, das zu tun.

Hier finden Sie aktuelle boost::shared_ptr. Es Sie mit Zeigern auf elegante Weise behandeln kann, ohne zu Pflege mit zu viel über ihre Streichung

class Foo {
public:
    boost::shared_ptr<int> p;
};

Foo *f1 = new Foo();
Foo *f2 = new Foo();
f1->p.reset(new int(1));
f2->p = f1->p;
delete f2; // ok
delete f1; // no error and its guaranteed !

Wenn Sie nicht boost verwenden möchten, einige Compiler bereits std::tr1::shared_ptr bereitzustellen, die ähnliche Semantik hat.

Wenn Sie mehrere Zeiger auf denselben Speicher verwenden möchten, kapseln sie in boost::shared_ptr, die sicherstellen, dass der zugrunde liegende Speicher nicht löschen-d, bis der letzte Verweis darauf Spielraum geht aus.

#include <boost/shared_ptr.hpp>

class Foo {
public:
    boost::shared_ptr<int> p;
    ~Foo() {
      p.reset();
    }
};

Foo *f1 = new Foo();
Foo *f2 = new Foo();
f1->p.reset(new int(1));
f2->p = f1->p;
delete f2; // ok
delete f1; // no error

Natürlich Doppel Löschungen sind nicht definiertes Verhalten. Es ist auch wahrscheinlich zu ändern, wenn zwischen Debug- und Release-Builds. Andere haben Sie die Güte von boost::shared_ptr weist darauf hin, und so weiter.

Es ist jedoch sinnvoll, auch zu erwähnen, wie man diese Art von Fehlern sicher finden kann:

Führen Sie Ihr Programm in valgrind .

Unter Windows purify ist der ältere, kommerzielle Pendant valgrind.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top