vector iterator memleak?



  • 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 verwenden

    Möglichkeit 2:
    boost::ptr_vector verwenden

    Ich 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.



  • pumuckl schrieb:

    Du kannst eine Funktion übergeben, die das Ziel zerstört und den Speicher freigibt.

    Genau das möchte ich tun. Destroy() ist die Methode des Objekts, die dies macht.

    vector<shared_ptr<Element> > vec; 
    vec.push_back(shared_ptr<Element>(GetElementPointer()), *GetElementPointer()->Destroy());
    

    Wäre das so machbar bzw. wäre dies auch mit einem boost::ptr_vector möglich?

    EDIT: Fehler im Code berichtigt.



  • Ich habe Möglichkeit 1 nun mal ausprobiert. Ich muss an jeder Stelle erst casten, das finde ich sehr unschön.

    ve.push_back((shared_ptr<Element>)GetElementPointer());
    


  • *push*


Anmelden zum Antworten