vector iterator memleak?
-
wenn du den vollen vector nicht sauber löscht dann ja, aber so sollte eigentlich nix passieren.
von der tatsache abgesehen, dass vector nicht dafür da ist pointer zu speichern, dafür gibts boost::ptr_vector oder wenigstens die möglichkeit smart pointer im vector zu halten
-
@Tachyon: Ich bin eigentlich davon ausgegangen, das kein memleak auftritt. Da ich so etwas ähnliches aber nun im großen Stil machen werde, wollte ich auf Nummer sicher gehen und erst nochmal nachfragen.
@Skym0sh0: Wenn ich vec.erase(it); nicht verwende, dürfte doch eigentlich auch kein memleak entstehen, solange ich mit delete die Objekte lösche, oder nicht?
Kannst du mir den gleichen Vorgang anhand eines boost::ptr_vector zeigen?
EDIT: In meinem Fall werde ich schon Pointer bekommen und möchte diese in den Container packen, wäre das dann auch noch mit einem boost::ptr_vector machbar?
-
also:
boost::ptr_vector ist darauf ausgelegt, dass beim destruktor aufruf (oder bei sonstigen lösch oder ähnlichen vorgängen) eine delete aufgerufen wird (das gibts glaub ich auch für delete[])
Docuein konkretes beispiel kann ich dir leider nicht geben, da ich mich (man möge mich mit schande überschütten) noch nie wirklich mit boost auseinander gesetzt habe

zu deienr frage:
du müsstest jedes objekt, auf das deine pointer zeigen, einzeln löschen. sei es durch:vector<string*> vec; // ... for(auto it = vec.begin(); it != vec.end(); ++it) delete *it; // oder durch for(size_t i = 0; i < vec.size(); ++i) delete vec[i];leaks entstehen wenn du den vector sich selbst löschen lässt, also er ohne weiteres zerstört wird (RAII...)
-
wobei der ptr_vector sollte eine ähnliche syntax sowie semantik haben wie der normale vector...
boost::ptr_vector<std::string> vec; vec.push_back( new std::string("a") ); auto it = vec.begin(); vec.erase(it);
-
DarkBug schrieb:
@Skym0sh0: Wenn ich vec.erase(it); nicht verwende, dürfte doch eigentlich auch kein memleak entstehen, solange ich mit delete die Objekte lösche, oder nicht?
Nein, aber eventuell das andere Extrem: double delete. In dem Moment, wo du das Objekt zerstörst, mußt du es auch aus dem vector herauswerfen, sonst kannst du hinterher nicht mehr erkennen, welche Einträge auf tatsächlich noch existierende Objekte verweisen und welche auf inzwischen freigegebene (und möglicherweise wiederverwendete) Speicherbereiche.
-
ja das kann auch passieren. also wenn du sowas machst, denk dran nur einmal löschen und um das zu gewährleisten, lösch den gerade gelöschten pointer direkt mit raus oder setz ihn wenigstens auf 0, dann macht ein neues delete nix falsch...
-
Skym0sh0 schrieb:
lösch den gerade gelöschten pointer direkt mit raus
Das ist der korrekte Ansatz.

Skym0sh0 schrieb:
oder setz ihn wenigstens auf 0, dann macht ein neues delete nix falsch...
Das ist kaschieren eines (logischen) Fehlers.

-
aber wer solche fragen stellt, dem reicht es auch die symptome zu bekämpfen statt die probleme

-
Das war nur eine Interessenfrage. Ich experimentiere gerade ein wenig.
string* testxy = new string("testxy"); ptr_vector<string>* ppvec = new ptr_vector<string>(); ppvec->push_back(new string("test")); ppvec->erase(find(ppvec->begin(), ppvec->end(), "test")); ppvec->push_back(testxy); ppvec->erase(find(ppvec->begin(), ppvec->end(), *testxy)); delete testxy; delete ppvec;Wieso muss ich in Zeile 9 direkt nach dem Objekt suchen (*testxy)? Das bedeutet doch, dass der ptr_vector direkt die Objekte verwaltet, anstatt deren Pointer. Ist das nicht ziemlich Performance beeinträchtigend. Wäre es da nicht doch besser einen std::vector mit Pointern zu benutzen?
-
Warum nimmst du new?
-
Um das Beispiel meinem Projekt anzunähern, denn ich muss eine Methode benutzen, die mir Pointer zurückgibt.
-
Man kann Pointer auch ohne new verwenden.
-
da hast du was falsch verstanden.
ein vector ist dazu da um daten zu speichern und auf ihnen auch zu operieren (per algorithm z.b.). wenn diese daten zeiger sind arbeiten deine algorithms auf den zeigern (sie sortieren also quasi die hausnummern deiner objekte der grösse nach, um mal ein abstraktes beispiel zu nennen)
ptr_vector ist dazu da um die zeiger auf deine daten zu verwalten und zu speichern. und etwaige operationen dadrauf gehen an den inhalt der zeiger. wieso solltest du auch zeiger der grösse ordnen im normalfall?!
und mach dir um performance mal keine gedanken. make it run, make it faster !
-
Ich würde dir auch empfehlen auf einen smartpointer zurückzugreifen. Wenn du schon mit memory leaks Probleme hast, frickelst du wahrscheinlich zuviel mit new rum. Es wurde hier ja schon ein paar mal erwähnt, welche du nutzen könntest.
http://www.boost.org/doc/libs/1_48_0/libs/smart_ptr/smart_ptr.htm
Da kannst du dir den raussuchen, der für deine Zwecke passt. Dann hast du dir das ständige new und (dringende) delete ersparrt.
-
Damit möchtest du mir sagen, das es keinen Sinn macht einen vector dynamisch zu erstellen, oder?
Wendet der ptr_vector in Zeile 9 ein delete auf das Objekt an, oder wird es nur aus dem ptr_vector entfernt?
-
DarkBug schrieb:
Wendet der ptr_vector in Zeile 9 ein delete auf das Objekt an, oder wird es nur aus dem ptr_vector entfernt?
nachlesen ist nicht?
aber: der container selbst führt das delete aus, wenn du das element aus dem vektor löschst.
-
DarkBug schrieb:
Damit möchtest du mir sagen, das es keinen Sinn macht einen vector dynamisch zu erstellen, oder?
Gegenfrage: Welchen Sinn sollte es machen? Die Vectoren sollen u.a. die Speicherverwaltung erleichtern, nicht zusätzlich erschweren (Ganz davon abgesehen gilt das gleiche für std::string).
DarkBug schrieb:
Wendet der ptr_vector in Zeile 9 ein delete auf das Objekt an, oder wird es nur aus dem ptr_vector entfernt?
ptr_vector kümmert sich um die Freigabe der Speicherbereiche, auf die die Zeiger verweisen, genau dafür ist er ja existent. In deinem Fall würde es daher beim Löschen des bereits gelöschten Eintrages zu undefinierten Verhalten kommen.
-
Ich habe folgendes gelesen: http://www.highscore.de/cpp/boost/smartpointers.html
Nun weiß ich aber nicht was in meinem Fall besser ist bzw. auch möglich ist, da ich die dynamischen Objekte nicht selber erstelle, sondern die Pointer davon aus einer Methode bekomme.
Möglichkeit 1:
std::vector + boost::shared_ptr verwendenMöglichkeit 2:
boost::ptr_vector verwendenIch arbeite mit einem Eventbasiertem System. Habe mir das nun mithilfe eines boost::ptr_vector in etwa so vorgestellt:
In der Klassendefinition des Frames:
ptr_vector<Element> pvec;Event: NeuesElementMussRein:
pvec.push_back(GetElementPointer());Event: EinAltesElementMussRaus:
pvec.erase(*GetElementPointer());User schließt das Programm, es sind aber noch Pointer die auf valide Objekte zeigen im Container. Im Destruktor des Frames:
pvec.clear();Wenn also erase() und clear() des boost::ptr_vector auch ein delete auf die Objekte anwendet, sollte dies ohne memleaks funktionieren, korrekt?
Welche der beiden Möglichkeiten ist für meinen Fall Performancetechnisch besser?
-
Dem boost::ptr_vector kann man keine Methode für den Destruktor des Objekts übergeben, wie man das beim boost::shared_ptr machen kann, oder? Wenn das nicht möglich ist, bleibt mir dann wohl keine andere Wahl und ich muss zu Möglichkeit 1 greifen und den std::vector + boost::shared_ptr verwenden.
-
DarkBug schrieb:
Dem boost::ptr_vector kann man keine Methode für den Destruktor des Objekts übergeben, wie man das beim boost::shared_ptr machen kann, oder?
Das kannst du beim shared_ptr auch nicht. Du kannst eine Funktion übergeben, die das Ziel zerstört und den Speicher freigibt. Kleiner Unterschied zum Destruktor. Standardmäßig ist das analog zu std::default_delete.