std::list::iterator Gültigkeitsfrage.



  • Ich hab in einem meiner Programme gerade einen Bug und hab ihn auf ein
    eine etwas unsaubere Stelle im Code zurückgeführt.

    1 Ich habe eine std::list, aus dieser Liste entferne ich ein Objekt
    behalte jedoch den Iterator der auf das Objekt verwies!
    old = *old_it;
    old_it = path.erase(old_it);

    2 Danach füge ich es wieder in die Liste ein.
    old_it = path.insert(old_it,old);
    Bis hierhin sollte eigentlich noch alles stimmen

    3 Jetzt lösche ich ein anderes Objekt aus der Liste (z.B. das direkt dahinter)
    act = *it;
    it = path.erase(it);

    4 Nun lösche ich das Alte wieder 🤡
    old_it = path.erase(old_it);

    5 Und füge das andere Objekt wieder ein
    it = path.insert(it,act);

    Ich habe die Vermutung das bei diesem Vorgang einer der beiden Iteratoren ungültig wird.
    D.h. wenn ich den Alten wieder lösche, der Iterator des Anderen Objektes ungültig wird.

    Der Bug macht sich übrigens in einer Endlosschleife bemerkbar. Der Schleifenkopf ist dabei:
    for(it=path.begin(); it != path.end(); it++)

    Ich weis das Alles ist etwas komplex, aber vllt. macht sich ja jemand
    die Mühe sich da kurz reinzudenken. Mir wäre auch schon geholfen wenn jemand
    sagt, ja der Iterator wird definitv ungültig, dann kann ich den Ganzen
    Ansatz gleich verwerfen.



  • Hmm erase gibt dir den Iterator für das nächste Item in der Liste zurück.



  • poste doch mal deinen quelltext, dann kann man dir vielleicht erzählen was sich genau abspielt.



  • *glaskugel herauskram*

    Storm.Xapek.de schrieb:

    1 Ich habe eine std::list, aus dieser Liste entferne ich ein Objekt
    behalte jedoch den Iterator der auf das Objekt verwies!
    old = *old_it;
    old_it = path.erase(old_it);

    2 Danach füge ich es wieder in die Liste ein.
    old_it = path.insert(old_it,old);
    Bis hierhin sollte eigentlich noch alles stimmen

    nö, du behältst nicht den iterator, auf den das element verwies. du behältst den wert ('old') und old_it zeigt nach dem erase des elements, auf das es zeigte, auf das element, das danach kommt.

    3 Jetzt lösche ich ein anderes Objekt aus der Liste (z.B. das direkt dahinter)
    act = *it;
    it = path.erase(it);

    aha, das ist das problem. das element, das direkt hinter dem gerade gelöschten kommt, ist das element, auf das old_it jetzt zeigt. erase invalidiert bei einer liste alle iteratoren auf das objekt, das gelöscht wird, damit zeigt old_it ab jetzt ins nirvana.

    4 Nun lösche ich das Alte wieder 🤡
    old_it = path.erase(old_it);

    und einen iterator, der ungültig ist, zu verwenden, fliegt dir um die ohren.

    5 Und füge das andere Objekt wieder ein
    it = path.insert(it,act);

    soweit kommt's wahrscheinlich gar nicht.

    std::list::erase invalidiert wie gesagt nur die iteratoren, die auf das gelöschte element zeigen. es lässt alle anderen unberührt.



  • Danke fürs durchlesen und für die Antworten.
    Ich habe den Ansatz inzwischen doch ganz verworfen...


Anmelden zum Antworten