Speichernutzungsverhalten von STL-Vector und Konsorten



  • Hallo alle.

    Ich schreibe gerade an einem größeren C++ Projekt und habe mir scheinbar auf dem Weg einen hässlichen bug eingehandelt der mir (glaube ich) stack corruption beschert. Symptome: Programm crasht mit Speicherzugriffsverletzungen an zufälligen (aber je nach user input und RNG-Seed reproduzierbaren) Stellen, teilweise "während" eines returns.

    Ich habe soweit möglich STL Objekte und auch Algorithmen verwendet, um die typischen memory allocation Fehler und fencepost errors von vornherein auszuschließen.

    Meine eigentliche Frage:
    std::vector ist soweit ich weiß im wesentlichen ein Wrapper für C-style arrays, die dynamisch (also auf dem heap) allokiert werden. Wenn also ein Objekt eine Matrix in Form eines vector<vector<unsigned> > als Membervariabel enthält, wird auf dem Stack im wesentlichen nur ein "Pointer" auf den Speicherbereich des äußeren vectors gespeichert? Ich frage, weil ich teilweise potenziell recht lange std::lists und std::vectors by value returnen muss, und ich möchte ausschließen, dass die beim returnen angelegte Kopie mir den stack corrupted oder überlaufen lässt.

    Als Bonusantwort (natürlich schwer ohne ein paar Stunden/Tage mit dem Code zu verbringen): Gibt es noch andere "typische" Fehler die man mit der STL machen kann, die das beschriebene Verhalten hervorrufen?

    Danke,

    Daniel



  • standard fehler ist, dass die elemente die du speicherst nicht korrekt kopiert werden. geh mit nem debugger durch. der fehler liegt ziemlich sicher nicht an der stl.



  • Ja, Vectoren sind im Prinzip Wrapper für normale Arrays mit dynmaischer Speicherdauer.
    Ein typischer Fehler, den man machen kann, ist das Arbeiten mit invalidierten Iteratoren oder invalidierten Zeigern auf Objekte in Containern.



  • Ich frage, weil ich teilweise potenziell recht lange std::lists und std::vectors by value returnen muss, und ich möchte ausschließen, dass die beim returnen angelegte Kopie mir den stack corrupted oder überlaufen lässt.

    sizeof(std::vector) ist unabhaengig von seiner Laenge oder dessen Inhalt.



  • ich vermute dass der vector im speicher fragmentiert vorliegen kann, da ich zufällig abstürze bekommen habe, als ich nach einem resize mit memcpy zusammenhängende daten in den freien speicher laden wollte. man musste erst die std::copy etc funktionen benutzen, damit alles wieder funktionierte.



  • ich vermute dass der vector im speicher fragmentiert vorliegen kann,

    Kann er nicht (seit dem Corrigendum von 2003).
    Simon



  • Wird memcpy genutzt? Bleibst du immer innerhalb der Grenzen des Arrays/Vectoren?

    Bedenke: Nur wenn du vector.at() nutzt prüft der Vector die Bounds, bei operator[] wird nicht geprüft!

    Ansonsten jag doch mal valgrind auf dein Programm.



  • ich blieb innerhalb der vectorgrenzen. aber es kam bei sehr großen dateninhalten sporadisch zum programmabsturz ohne assert. bei kleinen datenmengen funktionierte memcpy. das hat mich auch nicht sonderlich verwundert, da ich generell von std::vector nicht viel halte. aber es ist doch verwunderlich zumindest funktioniert die klasse wenn man bei std::copy bleibt. aber ansonsten sollte man erwägen immer selbst ein array mit eigenen []-operatorenm zu implementieren.



  • dgrat schrieb:

    das hat mich auch nicht sonderlich verwundert, da ich generell von std::vector nicht viel halte.

    Wundert mich nicht, wenn jemand gegen die Implementierung statt gegen die Schnittstelle programmiert.



  • wenn du einen vector<string> oder vector<vector> hast und memcpy benutzt, wird die kiste auch irgendwann abstürzen.



  • Danke für die Antworten, hat mir einige hilfreiche Ansatzpunkte geboten. Habe jetzt mal konsequent copy constructors, Zuweisungs- und Vergleichsoperatoren für meine Klassen geschrieben. Mir sind dabei zwar einige mögliche issues aufgefallen, die ich jetzt abfangen kann, aber das wars scheinbar nicht (leider). Werde mal weiter rumsuchen.

    Was valgrind angeht - ich bin leider auf ein Windowssystem beschränkt, muss da mal beim Chef etwas Lobbyarbeit betreiben. Nervt mich eh schon die ganze Zeit, dass die meisten guten Tools nicht laufen ^^



  • Für Windows gibts den Application Verifier.

    BTW: Wenn Du schon Copy DTOR und Assignment Operator gemacht hast, dürfte ein DTOR auch angebracht sein.

    Simon



  • Destruktoren schreibe ich immer, selbst wenn sie leer sind. Mit denen hatte ich schon zu viel Ärger.



  • theta schrieb:

    Für Windows gibts den Application Verifier.

    Sofern man MS Visual Studio verwendet.



  • Braunstein schrieb:

    theta schrieb:

    Für Windows gibts den Application Verifier.

    Sofern man MS Visual Studio verwendet.

    Die Alternative dazu wäre doch wohl MinGW, und für den gibts afaik auch valgrind.



  • The-Kenny schrieb:

    Die Alternative dazu wäre doch wohl MinGW, und für den gibts afaik auch valgrind.

    Aber nicht für Windows. Es gibt eine unter wine lauffähige Variante aber das wars auch schon.



  • Braunstein schrieb:

    theta schrieb:

    Für Windows gibts den Application Verifier.

    Sofern man MS Visual Studio verwendet.

    Muss nicht sein, kann auch separat gestartet werden.
    Simon



  • Daniel der Gast schrieb:

    ...aber das wars scheinbar nicht (leider).

    Das memcpy nicht unbedingt für Objekte geeignet ist, hast du aber auch verstanden? Und dabei ist es egal ob du auf C-Arrays oder std::vector setzt.



  • Memcpy verwende ich nicht. Alles was void* returned ist eh potenziell pfui ^^

    Ich _glaube_ übrigens ich hab den bug exterminiert, kann aber nicht mit Sicherheit sagen, was genau es war. Habe ein größeres refactoring der Methode gemacht, die den Fehler scheinbar verursacht hat, jetzt läufts (wohl).



  • Übrigens bin ich nicht identisch mit dgrat (nur um Verwirrung vorzubeugen)


Anmelden zum Antworten