Importer:Error:WasEmpty
-
cooky451 schrieb:
Nein, ein delete[] reicht. Du hast immer nur einen Pointer, auch wenn du das im gleichen Scope machen würdest.
Ich bin aber schon in der zweiten Funktion - also nicht mehr im selben Scope.
*Edit: Achso, es reicht demnach nur die Anfangsadresse aufzulösen und das OS gibt alles Folgende frei? Woher weiß das OS, wie viel Bytes nachfolgend freigegeben werden müssen, wenn ich außerhalb des Scope bin? Oder ist das irgendwie bei der Übergabe (return) irgendwo hinterlassen?
-
Ein delete[] reicht aus.
Mir ist nicht ganz klar woher delete[] weiss wieviele Elemente im Array sind, aber ich wuerde vermuten diese Information befindet sich entweder im Pointer selbst oder an der Speicheradresse auf die der Pointer zeigt, also im Array selbst.
http://www.cplusplus.com/reference/new/operator delete[]/
"operator delete[] can be called explicitly as a regular function, but in C++, delete[] is an operator with a very specific behavior: An expression with the delete[] operator, first calls the appropriate destructors for each element in the array (if these are of a class type), and then calls function operator delete[] (i.e., this function) to release the storage."Im Grunde gilt, alles was mit "new" geholt wird, muss auch wieder mit delete oder delete[] geloescht werden, ansonsten hat man ein Speicherleck.
Bei meinem ersten Beispiel oben mit dem Vector of Pointers habe ich also einen Vector voller Pointer die auf Objekte zeigen die mit "new" geholt wurden.
Wenn der Vector jetzt out of scope geht oder ich vec.clear(); benutze werden alle Objekte die auf dem Stack liegen (die Pointer) ordnungsgemaess geloescht.
Allerdings liegen die Objekte die mit "new" geholt wurden auf dem Heap und dort wird es erst mit dem Befehl "delete" weggeraeumt.
Das bedeutet, dass diese Objekte erst manuell geloescht werden muessen bevor ich den letzten Pointer verliere der auf diese jeweiligen Objekte zeigt.
-
Ruvi schrieb:
Ein delete[] reicht aus.
Mir ist nicht ganz klar woher delete[] weiss wieviele Elemente im Array sind, aber ich wuerde vermuten diese Information befindet sich entweder im Pointer selbst oder an der Speicheradresse auf die der Pointer zeigt, also im Array selbst.
http://www.cplusplus.com/reference/new/operator delete[]/
"operator delete[] can be called explicitly as a regular function, but in C++, delete[] is an operator with a very specific behavior: An expression with the delete[] operator, first calls the appropriate destructors for each element in the array (if these are of a class type), and then calls function operator delete[] (i.e., this function) to release the storage."Danke, es klingt logisch, eventuell ist es im Array selbst hinterlassen.
-
Ruvi schrieb:
Mir ist nicht ganz klar woher delete[] weiss wieviele Elemente im Array sind, aber ich wuerde vermuten diese Information befindet sich entweder im Pointer selbst oder an der Speicheradresse auf die der Pointer zeigt, also im Array selbst.
Der Compiler (g++) reserviert +4 bytes (sizeof(size_t)) vor dem array und speichert dort die Anzahl der Elemente.
#include <iostream> #include <new> class test { int i; // 4 bytes public: test() {std::cout << "ctor" << std::endl;} ~test() {std::cout << "dtor" << std::endl;} void* operator new[](size_t n) { void* result; result = ::operator new[](n); std::cout << "operator new[] size:" << n << " at:" << result << std::endl; return result; } }; int main(int, char**) { test* p = new test[2]; std::cout << "new test[2] at:" << p << std::endl; delete[] p; return 0; }operator new[] size:12 at:0x7e1050 ctor ctor new test[2] at:0x7e1054 dtor dtor- osdt
-
Danke, gut zu wissen.
-
osdt schrieb:
Der Compiler (g++) reserviert +4 bytes (sizeof(size_t)) vor dem array und speichert dort die Anzahl der Elemente.
#include <iostream> #include <new> class test { int i; // 4 bytes public: test() {std::cout << "ctor" << std::endl;} ~test() {std::cout << "dtor" << std::endl;} void* operator new[](size_t n) { void* result; result = ::operator new[](n); std::cout << "operator new[] size:" << n << " at:" << result << std::endl; return result; } }; int main(int, char**) { test* p = new test[2]; std::cout << "new test[2] at:" << p << std::endl; delete[] p; return 0; }Danke für den Hinweis,
ich wollte gerade den Code testen. Mein VC++6 sagt allerdings, dass in Zeile 15 der Befehl new[] kein Element von 'global namespace' ist. Man müsste den Operator nicht aus std entnehmen, sondern global lassen?
-
Dann ist was falsch, denn der Code läuft: http://ideone.com/kCe65G
-
Danke, der Code läuft unter Netbeans einwandfrei ... schient irgendetwas mit meiner heißgeliebten VC6 IDE zu sein http://lug-ottobrunn.de/wiki/Operator_New_in_CPP
-
VC6 ??? Der zugehörige Compiler ist noch nicht mal C++98 konform.
Nimm doch einfach das aktuelle VS Express.
-
Th69 schrieb:
VC6 ??? Der zugehörige Compiler ist noch nicht mal C++98 konform.
Nimm doch einfach das aktuelle VS Express.Ja, werde dann nur noch mit VS2010 Express u. Netbeans arbeiten

Nichtsdestotrotz denke ich, dass der Code, den osdt gepostet hat, keinen wirklichen Beweis liefert, da das Ganze in einer Klasse eingebetet ist und die Klasse kraft ihres Amtes die Auflösung der Zeigerelemente einleitet.
Gibt es eventuell eine andere Möglichkeit hinter die Kulissen zu schauen, vielleicht mit einem Debugger oder so, wo man die Speicherzellen direkt sieht und zum Testen ansprechen könnte? Also, ohne Hilfe von Klassen u. Strukturen.
-
Cpp_Anfaeger schrieb:
Nichtsdestotrotz denke ich, dass der Code, den osdt gepostet hat, keinen wirklichen Beweis liefert, da das Ganze in einer Klasse eingebetet ist ...
Damit hast du Recht. Der Code beweist nur, dass die Anzahl Elemente vom Compiler gespeichert wird (und werden muss) wenn es sich um Datentypen (Klassen) mit destructor handelt. Vor dem Aufruf des eigentlichen operator delete[] muss der Compiler den destructor (~test()) für jedes einzelne Element aufrufen (siehe Ausgabe 2x 'dtor').
Meine Aussage ...Der Compiler (g++) reserviert +4 bytes (sizeof(size_t)) vor dem array und speichert dort die Anzahl der Elemente.
gilt also nur in diesem Fall.
Für native (POD) Datentypen wie char[] oder int[] gilt dieses jedoch nicht.
char* p = new char[10];wird also nur 10 Bytes reservieren.
- osdt
-
Dies ist unabhängig vom Datentyp - denn irgendwie muß die Freigabefunktion (delete[] bzw. free() bzw. betriebssystemabhängige Funktion) ja wissen, wieviel Speicher sie wieder freigeben muß (eine andere Alternative wäre, daß intern eine Mappingtabelle <Speicheradresse, Groesse> benutzt würde).
-
Ich denke, dass wir immer nich einen Speicherleck haben, trotz: delete [] zeiger
Ich weiß eigentlich nicht, ob folgender Code den Speicherleck beweist, der immer noch da ist, oder?
#include <iostream> using namespace std; int main(int argc, char** argv) { int *p_array = new int[10]; // Zeiger auf ein Array im Heap int *p_merker = p_array; // p_merker simuliert die Übergabe (return) for (int i = 0; i < 10; i++) { *p_array = i; p_array++; } p_array = p_merker; delete [] p_merker; // Übergabe-Zeiger wird mit eckigen Klammern gelöscht for (int j = 0; j < 10; j++) { // Arrays immer noch vollständig da cout << j << ".: " << *p_array << endl; p_array++; } return 0; }
-
Der Code ist UB.
Das funktioniert nur, weil das Betriebssystem den Speicher noch nicht recycelt hat.
-
Nathan schrieb:
Der Code ist UB.
Das funktioniert nur, weil das Betriebssystem den Speicher noch nicht recycelt hat.Kann man es irgendwie merken, wann das OS den Speicher leert - vielleicht selbst anstoßen?
-
OK danke, alles klar

#include <iostream> using namespace std; void dummy(){ int *p_array = new int[10]; for (int i = 0; i < 10; i++) { *p_array = i; p_array++; } delete [] p_array; } int main(int argc, char** argv) { int *p_array = new int[10]; // Zeiger auf ein Array im Heap int *p_merker = p_array; // p_merker simuliert die Übergabe (return) for (int i = 0; i < 10; i++) { *p_array = i; p_array++; } p_array = p_merker; delete [] p_merker; // Übergabe-Zeiger wird mit eckigen Klammern gelöscht for (int j = 0; j < 10; j++) { // Array immer noch vollständig cout << j << ".: " << *p_array << endl; p_array++; } cout << "---------------------" << endl; dummy(); for (int j = 0; j < 10; j++) { // Array immer noch vollständig cout << j << ".: " << *p_array << endl; p_array++; } return 0; }
-
Cpp_Anfaeger schrieb:
Nathan schrieb:
Der Code ist UB.
Das funktioniert nur, weil das Betriebssystem den Speicher noch nicht recycelt hat.Kann man es irgendwie merken, wann das OS den Speicher leert - vielleicht selbst anstoßen?
Ja, mit delete. Damit gibst du Speicher an das OS zurück.
Du darfst denn danach nicht mehr verwenden!
Ob das OS den Speicher schon erneut verwendet, hängt damit zusammen wie viele andere Prozesse Speicher anfordern etc..
Aber dir gehört er nicht mehr.
Und du darfst dich auch nicht darauf verlassen, dass ein erneuter Call zu new denselben Speicher zurückgibt!
-
@Cpp_Anfaeger
Zum Vermeiden solcher Fehler gibt es gute Hilfsmittel, wie z.B. die Debug-Heap Funktionen unter Windows.
Mittels derer kann man es einrichten dass freigegebener Speicher mit einem bestimmten Muster gefüllt wird (üblicherweise0xdddddddd). Visual C++ aktiviert diese Funktionen per Default inRelease-BuildsDebug-Builds.Und wenn dein Programm in einer solchen Umgebung läuft, würdest du anhand der "komischen Zahlen" die von der 2. Ausgabeschleife ausgegeben werden merken dass etwas nicht so läuft wie es sollte.
Auf Linux gibt es vermutlich ähnliche Funktionen/Tools. Bzw. auch Programme wie valgrind, die helfen können solche (und andere) Fehler zu finden.
EDIT: Blödsinn korrigiert.
-
hustbaer schrieb:
in Release-Builds.
Bist du dir sicher dass das im Release so ist und nicht im Debug-Build?
Ich kann mich auch irren, möchte nur dazulernen...
-
Nein, gar nicht. Ganz im Gegenteil.
Ich bin mir sicher dass ich Blödsinn geschrieben habe.
Danke für den Hinweis!