Möglicher Speicherverlust mit C ++ - Zeichenfolge

7

Betrachten Sie das folgende C ++ - Programm:

%Vor%

Wenn Sie dies durch Valgrind ausführen, wird dies angezeigt (einige Ausgaben wurden der Kürze wegen gekürzt):

%Vor%

Wie Sie sehen können, gibt es eine Möglichkeit , dass auf dem Heap zugewiesene 26 Byte verloren gegangen sind. Ich weiß, dass die std::string -Klasse eine 12-Byte-Struktur hat (zumindest auf meinem 32-Bit-x86-Arch und GNU-Compiler 4.2.4), und "Hallo, Welt!" mit einem Null-Terminator hat 14 Bytes. Wenn ich es richtig verstehe, enthält die 12-Byte-Struktur einen Zeiger auf die Zeichenfolge, die zugewiesene Größe und die Referenzzahl (jemand korrigiert mich, wenn ich hier falsch liege).

Nun meine Fragen: Wie werden C ++ - Strings in Bezug auf den Stack / Heap gespeichert? Existiert ein Stack-Objekt für ein std::string (oder andere STL-Container) bei der Deklaration?

P.S. Ich habe irgendwo gelesen, dass Valgrind in einigen C ++ - Programmen, die STL-Container verwenden (und "fast-containers" wie std::string ) ein falsches positives Ergebnis eines Speicherlecks meldet. Ich mache mir keine Sorgen wegen dieses Lecks, aber es macht meine Neugier auf STL-Container und Speicherverwaltung wecken.

    
pr1268 22.11.2010, 21:13
quelle

5 Antworten

7

Andere sind richtig, Sie sind undicht, weil Sie den Ausgang aufrufen. Um klar zu sein, ist das Leck nicht die auf dem Stapel zugewiesene Zeichenfolge, es ist Speicher, der auf dem Heap durch die Zeichenfolge zugewiesen wird. Zum Beispiel:

%Vor%

bewirkt nicht, dass valgrind ein Leck meldet.

Das Leck ist wahrscheinlich (anstelle von definitiv), weil Sie einen inneren Zeiger auf Speicher haben, der auf dem Heap reserviert ist. basic_string ist dafür verantwortlich. Aus der Kopfzeile meines Computers:

%Vor%

Der Schlüssel ist, dass _M_p nicht auf den Anfang des im Heapspeicher zugewiesenen Speichers zeigt, sondern auf das erste Zeichen in der Zeichenfolge. Hier ist ein einfaches Beispiel:

%Vor%

Dies wird ein wahrscheinliches Leck in Valgrind melden. Wenn Sie die Zeilen, an die ich mich bewege, auskommentieren, meldet m_data valgrind 'immer noch erreichbar'. Wenn Sie die Zeile, in der ich m_data auf 0 gesetzt habe, auskommentieren, erhalten Sie ein eindeutiges Leck.

Die valgrind Dokumentation enthält weitere Informationen zu möglichen Lecks und inneren Hinweisen.

    
jmnas 23.11.2010, 02:21
quelle
11

Aufruf von exit beendet das Programm, ohne den aktuellen Block zu verlassen und somit ohne Löschen von Objekten mit automatischer Speicherdauer ".

Mit anderen Worten, leckt oder nicht, Sie sollten sich nicht wirklich darum kümmern. Wenn Sie exit aufrufen, sagen Sie "Schließen Sie dieses Programm, mir ist nichts mehr daran interessiert." Also hör auf dich zu kümmern. :)

Offensichtlich wird es Ressourcen verlieren, weil Sie niemals den Destruktor der Zeichenfolge ausführen lassen, ganz gleich wie diese Ressourcen verwaltet werden.

    
GManNickG 22.11.2010 21:18
quelle
4

Natürlich ist dies "leaks", indem exit ing vor s 's stack frame übrig bleibt, geben Sie s ' s destructor keine Chance zur Ausführung.

Was Ihre Frage betrifft std::string storage: Verschiedene Implementierungen machen verschiedene Dinge. Einige ordnen dem Stapel 12 Byte zu, der verwendet wird, wenn die Zeichenfolge 12 Byte oder kürzer ist. Längere Strings gehen zum Heap. Andere Implementierungen gehen immer zum Heap. Einige sind Referenz gezählt und mit Copy-on-Write-Semantik, andere nicht. Bitte wenden Sie sich an Scott Meyers ' Effective STL , Punkt 15.

    
dennycrane 22.11.2010 21:17
quelle
1

gcc STL verfügt über einen privaten Speicherpool für Container und Strings. Sie können dies ausschalten; Schau in Valgrind FAQ

Ссылка

    
pm100 22.11.2010 21:15
quelle
1

Ich würde vermeiden, exit () zu verwenden. Ich sehe keinen wirklichen Grund, diesen Anruf zu verwenden. Nicht sicher, ob der Prozess sofort gestoppt wird, ohne zuerst den Speicher zu bereinigen, obwohl Valgrind weiterhin ausgeführt wird.

    
CashCow 22.11.2010 21:18
quelle

Tags und Links