std::vector - iterator not dereferancable



  • Hallo,
    Mir ist bewusst das dieses Thema bereits sehr oft besprochen wurde allerdings hat keine der Lösungen für mich funktioniert.

    Wenn ich versuche ein Objekt aus meinem Vector zu löschen bekomme ich die Fehlermeldung "list iterator not dereferencable".

    Soweit ich weiß beudeutet das, dass ich aus der Range meines Vectors gerate oder in einer Endloschleife lande

    Allerding erhalte ich immer noch die selbe Meldung nachdem ich mich mehrmals vergewissert habe das keiner der beiden Fälle eintritt.

    std::list<Projectile*> pVec;
    
    for (auto it = pVec.begin(); it != pVec.end(); it++)
    {
    	if (!size.contains((*it)->getPosition()))
    	{
    		it = pVec.erase(it);
    
    		delete (*it);
    	}
    }
    

    Projectile ist ein Objekt von einer von mir erzeugten Klasse, dessen Methoden ich über den Iterator aufrufe, was auch super funktioniert.
    Wenn ein Projectil nun mein Fenster verlässt soll es aus der Liste gelöscht werden und zerstört werden, jedoch tritt bei beiden Befehlen die oben gennante Fehlermeldung auf.

    Ich habe diese Schema schon in früheren Projekten benutzt und es hat, nachdem ich mich vergewisster habe das ich weder out of range gerate noch in eine Endlosschleife auch immer super funktioniert.

    Vielen Dank für jedliche hilfe!


  • Mod

    Please provide a minimal, but complete, example for your problem. The code you are currently showing us does not match your description of the problem, starting with the fact that your code uses std::list, whereas you and the error messages speak of std::vector. A guide how to create such an example can be found here (in German):
    https://www.c-plusplus.net/forum/304133
    If you do not speak German I can give you a quick summary:
    -Remove anything from the Code that does not have to do with your problem
    -Important: Check if the problem persists!
    -Repeat steps 1 and 2 until you cannot remove any more parts of your program without removing the error
    -Copy the contents of all headers and all source files into one, if able. In the end, there should only be one to three (preferably only one) pieces of code left
    -Check if the problem persists!
    -Post your code here.

    In general, you are most probably doing something very wrong in the ways of memory management if a delete -statement shows up like it does in your code. This indicates that you probably do not properly manage your other resources, either. I bet all your problems will solve themselves if you use the RAII idiom to manage your resources, as was intended by the designers of C++.

    edit: Huch, jetzt hast du gemerkt, dass dies ein hauptsprachlich deutsches Forum ist? Dann wirkt meine Antwort natürlich etwas bizarr, aber ich mache mir jetzt mal nicht die Mühe, alles noch einmal auf Deutsch zu formulieren 🙂



  • SeppJ schrieb:

    Dann wirkt meine Antwort natürlich etwas bizarr

    Hab ich mir auch gedacht 🙂



  • it = pVec.erase(it);
    

    erase() gibt einen Iterator auf den Nachfolger des zu löschenden Elements zurück.
    Falls das letzte Element von pVec ein Löschkandidat ist, so ist dieser Nachfolger der end() -Iterator,
    der nicht dereferenzierbar ist, da er konzeptionell auf "eins hinter der Liste" verweist, wordurch

    delete (*it);
    

    entsprechend fehlschlägt (und auch wenn es nicht fehlschlägt, so wird der falsche Pointer gelöscht).
    Ein weiteres Problem ist das inkrementieren des Iterators im Schleifenkopf:

    for (auto it = pVec.begin(); it != pVec.end(); it++)
    

    Im Falle eines erfolgreichen Löschens verweist it bereits auf den
    Nachfolger des gelöschten Elements, wird aber beim nächsten Schleifendurchlauf
    nochmal inkrementiert. D.h. bei jedem Löschvorgang überspringst du den direkten Nachfolger und prüfst nicht,
    ob dieser ebenfalls gelöscht werden muss.

    Korrekt wäre (ungetestet):

    for (auto it = pVec.begin(); it != pVec.end(); )
    {
        if (!size.contains((*it)->getPosition()))
        {
            delete (*it);
            it = pVec.erase(it);
        }
        else
            it++;
    }
    

    Die Informationen, wie z.B. erase() funktioniert, sind übrigens diversen
    C++-Referenzen/Dokumentationen zu entnehmen.

    Gruss,
    Finnegan



  • WhiiTESHaDoOW schrieb:

    Wenn ich versuche ein Objekt aus meinem Vector zu löschen bekomme ich die Fehlermeldung "list iterator not dereferencable".

    Das ist doch nett! Dann verwendest Du einen Debug-Modus der Standardbibliothek, der dir eigentlich schon ziemlich genau sagt, was das Problem ist -- anstatt dir sonst irgendwie komisch abzustürzen.

    Das Problem wurde ja schon erklärt.

    Ich frage mich aber, warum Du gerade std::list<Projectile*> verwenden willst. Was spricht z.B. gegen std::list<Projectile> oder std::vector<std::unique_ptr<Projectile>> oder std::vector<Projectile> ? Was ist da Dein Gedankengang? Dass Du hier nämlich manuell delete verwenden musst, ist schon eher suboptimal.


Anmelden zum Antworten