Deallocation von rekursiv erstellten Objekten
-
Hallo zusammen
Ich habe ein Programm geschrieben zum berechnen eines N-Körper Problems (2D) mit der Fast Multipole Method. Dabei wird die Quadratische Welt sukzesive in 4 glech grosse Quadrate (Box) geteilt, bis in jeder Box nur noch Nmax Partikel sind.
Das Programm funktioniert, jedoch habe ich das Problem, dass es sehr viel Speicher benötigt. Für 1e5 Iterationsschritte (die Teilung der Welt wird bei jedem Iterationsschritt neu ausgeführt => >200 Boxen pro Schritt) benötigte das Programm ca. 3GB Speicher!
Ich glaube es liegt daran dass die mit
newerstellten Boxen nicht wieder freigegeben werden.
Der dazu relevante Code ist unten angehängt.
struct Box { // Members: bool bEmpty; // true if leaf node std::complex<float> a[8]; // Multipole expansions of the Box-center Box *Parent; Box *Children[4]; // Boxes of the 4 children float width; // size of box std::complex<float> center; unsigned int idx_start; // start of particles in data-vector unsigned int Np; // number of particles in Box // Constructor: Box(Box*, bool , float , float* , unsigned int , unsigned int); ~Box(); // Split particles in Boxes and recursively create boxes: void Split(std::vector<Box*>&,std::vector<Particle> &, const int); }; //////////////////////////////////////////////////////////////////////////////////////////////////////////// void Box::Split(/*....*/) { // ...... some code......... for (int i=0;i<4;i++) { // create children-box: Children[i] = new Box(this->Parent,false, width*0.5, centerChild, idx_s, NpChild[i]); // split data in children-box again: Children[i] -> Split(/*.....*/); } }//end Split()Ist es notwendig dass die mit "new" erstellten Boxen wieder gelöscht werden?
Wie macht man das? die stl::vector lösche ich mit .clear(), wie macht man das für die rekursiv erstellten Objekte (Box)?
-
Mit
newerstellte Objekte werden mitdeletegelöscht, bei C-Arrays muss mandelete[]benutzen.
Alternativ kann man Smart-pointers einsetzen. Es gibt dazu einen Artikel im Magazin hier: http://magazin.c-plusplus.net/artikel/Schlaue%20Zeiger%20-%20Boost%20Smart%20Pointer.shared_ptrundweak_ptrsind bei neueren Compilern auch nach#include <memory>unterstd::tr1::vorhanden.
EDIT: Siehe auch http://www.cplusplus.com/doc/tutorial/dynamic/, Absatz "Operators delete and delete[]"
-
-
padreigh, ja die Box Struktur ist ein Quadtree.
Oberon_0, dann müsste ich jedes Children mit delete löschen können. Also habe ich dies versucht:
Box::~Box(){ for (int i=0;i<4;i++) { if (Children[i] != NULL) { Children[i]->~Box(); delete Children[i]; } } }Der Versuch dies für die top-level Box rootBox.~Box() aufzurufen führte zum Absturz des Programms.
-
Nach langem studieren der Literatur
und einigem Ausprobieren habe ich die Lösung gefunden:Box::~Box(){ for (int i=0;i<4;i++) { delete Children[i]; Children[i]=NULL; } }Dies wird für die rootBox automatisch bei beendigung der Funktion ausgeführt.