speicherzugriffsfehler bei mehr als 262091 elementen in einer liste



  • Ähm, Dein Destructor von MyListElement sieht sehr nett aus.
    Könnte es sein, dass Dir der Stack ausgeht?
    Der Stackframe dürfte 262091 Aufrufe gross sein.
    Ausserdem ist es so ziemlich gefährlich. Irgendwo ein MyListElement zerstören ohne vorher next auf NULL gesetzt zu haben, zerschiesst Dir Deine Liste (CopyConstructor, temporäre Objekte)



  • niemand schrieb:

    Ähm, Dein Destructor von MyListElement sieht sehr nett aus.

    meinst du das positiv, oder negativ?
    wie sollte man es denn machen? / was ist daran falsch?
    (war nicht meine idee, stand so im scriptum der uni marburg http://www.mathematik.uni-marburg.de/~cpp/pointer/listedef.html

    niemand schrieb:

    Könnte es sein, dass Dir der Stack ausgeht?
    Der Stackframe dürfte 262091 Aufrufe gross sein.

    kann sein..
    von was haengt das ab, und kann man das umgehen?
    und warum kann ich dann eine 2. liste mit nochmal 200k elementen machen?

    niemand schrieb:

    Ausserdem ist es so ziemlich gefährlich. Irgendwo ein MyListElement zerstören ohne vorher next auf NULL gesetzt zu haben, zerschiesst Dir Deine Liste (CopyConstructor, temporäre Objekte)

    das hab ich glaub ich beachtet (oder?)



  • die Sache mit dem destructor war negativ gemeint 😉

    Veränder den destructor deiner liste besser so, dass du zuerst das letzte element löscht, dann das vorletzte, usw, bis kein element mehr da ist. Das problem deines destructors, bzw des destructors deiner elemente ist, dass sie sich rekursiv aufrufen. Und jeder aufruf kostet etwas speicherplatz auf dem Stack. Der Stack hat aber eine Beschränkung der größe, die man zwar verändern kann, aber die trotzdem nicht so groß ist.

    oder machs dir ganz einfach, und benutz std::list<T> statt deiner Liste 😃



  • Definitiv negativ.

    Grundsätzlich erscheint es mir keine gute Idee Objekte zu zerstören über die ich nichts weiss. Gewöhnlich sollte ein Objekt nur die Resourcen wieder freigeben, die es besitzt.
    In Deinem Fall wäre der Besitzer wohl am ehesten MyList<T>. Also sollte die auch über alle Listenelemente iterieren und diese zerstören.
    Das Verhalten ist übrigens anders als es bei der erwähnten std::list<T> ist:
    std::list<T> erwartet keine Pointer, sondern kopierbare Objekte, während std::list<T*> Pointer erwartet, die Objekte dahinter aber nicht zerstört (beim Zerstören der Liste).

    Zum Thema Kopien:
    Du machst in Deinem Code vermutlich alles richtig, Du verhinderst aber mögliche Fehler nicht.
    Du hast keinen CopyConstructor überschrieben. Würdest Du (oder jemand anders, der Deinem Code erweitert), also beispielsweise:

    {
      MyListElemet<T> x = *first_element;
      // damit etwas machen
    }
    

    wäre am Ende des Blocks die Liste komplett gelöscht. (x enthält Kopien auf die Zeiger von first_element, beim Verlassen des Blocks wird der Destruktor von x aufgerufen und die Liste gelöscht).
    Um das zu verhindern, kann man z.B. den CopyConstructor und Assignment Operator private machen, dann kann niemand eine solche Zeile hinschreiben.



  • aMan schrieb:

    niemand schrieb:

    Könnte es sein, dass Dir der Stack ausgeht?
    Der Stackframe dürfte 262091 Aufrufe gross sein.

    kann sein..
    von was haengt das ab, und kann man das umgehen?
    und warum kann ich dann eine 2. liste mit nochmal 200k elementen machen?

    Weil die Destruktoren beider Listen separat aufgerufen werden. Somit verlängert sich nicht die Rekursionskette, die du bei deinem jetzigen rekursiven Desktruktor erzeugst.

    Ich würde die Destruktion der Listenelemente rein iterativ in deiner Listenklasse durchführen. Also eine Schleife, die so lange das nächste Element löscht, bis keins mehr da ist (next NULL ist).



  • danke leuds, jetzt verstehe ich, was ihr meint..

    ich werde das aendern..

    gibts vielleicht eine seite, die den stack usw genauer erklaert?



  • hm.
    , kA, aber soviel gibts da auch nicht zu wissen...
    alle variablen, die du nicht mit new allokierst liege auf dem Stack->mit jeder variablen wird der stackpointer größer (der zeigt auf das ende, also die Spitze vom Stack), außerdem wird, wenn du eine funktion aufrufst die Rücksprungaddressefür diese funktion auf dme Stack abgelegt, und es werden auch die Parameter für die funktionen auf dem Stack abgelegt. Bei häufigem rekursiven aufruf von funktionen wird der stackpinter also immer größer und irgendwann ist kein Platz mehr auf dem Stack und du bekommst so einen schönen Ausnahmefehler 😉



  • volgendes:

    Volkard - aber
    Folgendes



  • @maxi
    danke..

    liegt der stack denn im prozi, oder im ram?

    @rechtschreibtroll
    vogel V fehler mach ich oft..
    ich muss mich auch jedes mal ne runde schaemen..



  • der stack liegt m RAM, so wie der Heap auch, is nur eben "räumlich", also von der Größe auf eine ziemlich kleine Menge begrenzt



  • ok, thx..


Anmelden zum Antworten