Nach einer Diskussion in einem Software-Meeting habe ich herausgefunden, ob das Löschen eines dynamisch zugewiesenen primitiven Arrays mit der einfachen delete
einen Speicherverlust verursachen wird.
Ich habe dieses winzige Programm geschrieben und es mit Visual Studio 2008 unter Windows XP kompiliert:
%Vor%Ich habe dann den Speicherverbrauch meiner Anwendung mithilfe des Task-Managers überwacht. Überraschenderweise wurde der Speicher korrekt zugewiesen und freigegeben. Der zugewiesene Speicher stieg nicht wie erwartet an.
Ich habe mein Testprogramm geändert, um ein nicht-primitives Array zuzuordnen:
%Vor%Nach 10 Minuten Laufzeit gab es keine nennenswerte Speichererweiterung
Ich habe das Projekt mit Warnstufe 4 kompiliert und keine Warnungen erhalten.
ist es möglich, dass die Visual Studio-Laufzeit die zugewiesenen Objekttypen verfolgt, so dass es zwischen delete
und delete[]
in dieser Umgebung keinen Unterschied gibt?
lösche p, wobei p ein Array ist, heißt undefiniertes Verhalten.
Insbesondere, wenn Sie ein Array von Rohdatentypen (ints) zuweisen, hat der Compiler nicht viel zu tun, also verwandelt er es in ein einfaches malloc (), also wird delete p wahrscheinlich funktionieren.
delete p wird normalerweise fehlschlagen, wenn:
Nein, das Verhalten ist nicht definiert. Tu es nicht - benutze delete[]
.
In VC ++ 7 bis 9 funktioniert es wenn der fragliche Typ einen trivialen Destruktor hat , aber es könnte aufhören, an neueren Versionen zu arbeiten - übliche Sachen mit undefiniertem Verhalten. Tu es trotzdem nicht.
Es heißt undefiniertes Verhalten ; es könnte funktionieren, aber Sie wissen nicht warum, also sollten Sie nicht dabei bleiben.
Ich glaube nicht, dass Visual Studio verfolgt, wie Sie die Objekte zugewiesen haben, als Arrays oder einfache Objekte und fügt []
Ihrem Löschen dynamisch hinzu. Es kompiliert wahrscheinlich delete p;
zu dem gleichen Code wie wenn Sie mit p = new int
zugewiesen haben, und, wie gesagt, aus irgendeinem Grund funktioniert es. Aber Sie wissen nicht warum.
Eine Antwort ist, dass es Speicherlecks verursachen kann, weil es den Destruktor nicht für jedes Element im Array aufruft. Das bedeutet, dass zusätzlicher Speicher, der Eigentum von Elementen im Array ist, ausläuft.
Die mehr standardkonforme Antwort ist, dass es ein undefiniertes Verhalten ist. Beispielsweise hat der Compiler das Recht, unterschiedliche Speicherpools für Arrays zu verwenden als für Nicht-Array-Elemente. Die neue Einwegmethode, aber das Löschen der anderen Datei, kann zu einer Beschädigung des Heapspeichers führen.
Ihr Compiler kann garantieren, dass der Standard dies nicht tut, aber das erste Problem bleibt bestehen. Für POD-Elemente, die keinen zusätzlichen Speicher (oder Ressourcen wie Dateihandles) besitzen, könnten Sie OK sein.
Auch wenn es für Ihren Compiler und Datenelemente sicher ist, tun Sie es trotzdem nicht - es ist auch irreführend für jeden, der versucht, Ihren Code zu lesen.
Wenn Sie delete
verwenden, werden die Destruktoren der Objekte im Array nicht aufgerufen. Während es möglicherweise wie beabsichtigt funktioniert, ist es undefiniert, da es einige Unterschiede gibt, genau wie sie funktionieren. Sie sollten es also nicht verwenden selbst für integrierte Typen .
Der Grund dafür, Speicher nicht auslaufen zu lassen, liegt darin, dass das Löschen in der Regel auf dem freien Speicher basiert, der bereits weiß, wie viel Speicher er frei braucht. Es ist jedoch unwahrscheinlich, dass der C ++ Teil korrekt bereinigt wird. Ich wette, dass nur der Destruktor des ersten Objekts aufgerufen wird.
Die Verwendung von delete mit [] weist den Compiler an, den Destruktor für jedes Element des Arrays aufzurufen. Wenn Sie delete [] nicht verwenden, können Speicherverluste auftreten, wenn sie in einem Array von Objekten verwendet werden, die dynamische Speicherzuweisungen wie folgt verwenden:
%Vor%Tags und Links c++ memory-management