Frage

Ich erhalte einen schlechten Fehler. Als ich an der Spitze einer Objekthierarchie auf ein Objekt löschen nennen (auf die Ursache der Hoffnung, die Löschung seiner untergeordneten Objekte), mein Progamm beendet und ich bekomme diese:

*** glibc detected *** /home/mossen/workspace/abbot/Debug/abbot: double free or corruption (out): 0xb7ec2158 ***

, gefolgt von dem, was wie ein Speicherabbild einer Art sieht. Ich habe für diesen Fehler gesucht und von dem, was ich sammle es scheint auftreten, wenn Sie Speicher zu löschen versuchen, die bereits gelöscht wurde. So unmöglich es nur einen Platz in meinem Code ist, der diese löschen versucht. Hier ist der verrückteste Teil: es ist nicht im Debug-Modus auftritt. Der Code in Frage:


Terrain::~Terrain()
{
    if (heightmap != NULL) // 'heightmap' is a Heightmap*
    {
        cout << "heightmap& == " << heightmap << endl;
        delete heightmap;
    }
}

Ich habe alles in der heightmap destructor auf Kommentar, und noch diesen Fehler. Wenn der Fehler auftritt,

heightmap& == 0xb7ec2158

wird gedruckt. Im Debug-Modus kann ich Schritt durch den Code langsam und

heightmap& == 0x00000000

ist gedruckt, und es gibt keinen Fehler. Wenn ich die ‚löschen heightmap;‘ auf Kommentar Linie, Fehler nie auftritt. Der destructor oben von einem anderen destructor (getrennten Klassen, keine virtuellen Destruktoren oder ähnlichem) genannt. Der heightmap Zeiger wird in einem Verfahren, wie diese new'd:


Heightmap* HeightmapLoader::load() // a static method
{
   // ....
   Heightmap* heightmap = new Heightmap();
   // ....other code
   return heightmap;
}

Könnte es etwas sein, mit der Rückkehr einen Zeiger zu tun, die in dem Stapelspeicher einer statischen Methode initialisiert wurde? Mache ich das richtig löschen? Alle andere Tipps, was ich für überprüfen könnte, oder besser machen?

War es hilfreich?

Lösung

Was passiert, wenn load() nie aufgerufen wird? Hat Ihr Klassenkonstruktor heightmap initialisieren, oder ist es nicht initialisiert, wenn es um den destructor wird?

Auch Sie sagen:

  

... Speicher löschen, die bereits gelöscht wurde. So unmöglich es nur ein Platz in meinem Code ist, dass diese löschen versucht.

Sie haben jedoch nicht berücksichtigt, dass Ihr destructor genannt werden könnte mehr als einmal während der Ausführung des Programms.

Andere Tipps

Im Debug-Modus Zeiger werden oft auf NULL und Speicherblöcke auf Null gesetzt aufgeführt. Das ist der Grund, warum Sie ein anderes Verhalten im Debug / Release-Modus auftritt.

Ich würde vorschlagen, dass Sie einen intelligenten Zeiger statt eines traditionellen Zeiger verwenden

auto_ptr<Heightmap> HeightmapLoader::load() // a static method
{
   // ....
   auto_ptr<Heightmap> heightmap( new Heightmap() );
   // ....other code
   return heightmap;
}

auf diese Weise brauchen Sie nicht um es später zu löschen, da sie automatisch für Sie erledigt werden

siehe auch boost :: shared_ptr

Es ist durchaus möglich, dass Sie das dtor zweimal sind gefordert wird; im Debug-Modus ist nun mal die Zeiger auf Null gesetzt Lösch werden, in optimierten Modus es allein gelassen wird. Während keine saubere Lösung, die erste Abhilfe, die in den Sinn kommt, ist heightmap = NULL; direkt nach dem Löschen Einstellung - es sollte nicht notwendig sein, aber sicher nicht schaden kann, während Sie für die Erklärung, warum suchen Sie etwas Terrain sind zerstört Beispiel zweimal! -) [[es gibt absolut nichts in der kleinen Menge an Code sind zeigen Sie, dass Sie uns zu erklären, den Grund für die Doppel Zerstörung helfen kann.]]

Es sieht aus wie der klassische Fall von nicht initialisierten Zeiger. Wie @ Greg sagte, was ist, wenn Last () nicht aus Terrain genannt? Ich glaube, Sie sind nicht die HeightMap* Zeiger innerhalb des Terrain Konstruktor initialisiert. Im Debug-Modus kann dieser Zeiger auf null gesetzt werden und C ++ GARANTIEN, dass ein NULL-Zeiger zu löschen eine gültige Operation ist und daher wird der Code nicht zum Absturz bringen. im Release-Modus aufgrund Optimierungen, versuchen Sie den Zeiger jedoch in nicht initialisierten und Sie einigen zufälligen Speicherblock und der oben Absturz zu befreien.

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