Ich benutze eine C-Bibliothek in C ++ und habe einen Wrapper geschrieben. An einem Punkt muss ich eine std::string
in eine c-style Zeichenfolge konvertieren. Es gibt eine Klasse mit einer Funktion, die eine Zeichenfolge zurückgibt. Die Rückgabe der zurückgegebenen Zeichenfolge funktioniert, wenn die Zeichenfolge kurz ist, andernfalls nicht. Hier ist ein einfaches und reduziertes Beispiel, das das Problem veranschaulicht:
Wenn Sie die obige Datei ausführen, wird dies auf der Konsole angezeigt:
castString:
Wenn ich hingegen die Kommentare zu someString
vertausche, druckt es
castString: Hallo
Wie ist das möglich?
Sie rufen c_str
für ein temporäres String-Objekt auf, das durch die% member-Funktion getString()
neu ausgerichtet wurde. Der von c_str()
zurückgegebene Zeiger ist nur so lange gültig, wie das ursprüngliche Zeichenfolgenobjekt existiert. Am Ende der Zeile, der Sie castString
zuweisen, ist es also ein Dangling-Zeiger. Offiziell führt dies zu undefiniertem Verhalten.
Warum funktioniert das für kurze Saiten? Ich vermute, dass Sie die Auswirkungen der Short String Optimization sehen, einer Optimierung, bei der die Zeichendaten für Strings mit weniger als einer bestimmten Länge innerhalb der Bytes des String-Objekts selbst und nicht im Heap gespeichert werden. Es ist möglich, dass die temporäre Zeichenfolge, die zurückgegeben wurde, auf dem Stapel gespeichert wurde. Wenn sie bereinigt wurde, sind keine Zuordnungen aufgetreten und der Zeiger auf das abgelaufene Zeichenfolgenobjekt enthält weiterhin die alten Zeichenfolgenbytes. Dies scheint mit dem übereinzustimmen, was Sie sehen, aber es bedeutet immer noch nicht, dass Sie eine gute Idee haben. : -)
box.getString()
ist ein anonymes temporäres . c_str()
gilt nur für die Länge der Variablen.
In Ihrem Fall wird also c_str()
ungültig gemacht bis Sie zu std::cout
gelangen. Das Verhalten beim Lesen des Zeigerinhalts ist undefiniert .
(Interessanterweise ist das Verhalten Ihrer kurzen Zeichenfolge möglicherweise anders, da std::string
kurze Zeichenfolgen auf andere Weise speichert.)
box.getString()
erzeugt eine temporäre. Wenn Sie c_str()
aufrufen, erhalten Sie einen Zeiger auf ein temporäres Objekt. Nachdem das temporäre nicht mehr existiert, ist der Zeiger ungültig, ein dangling pointer .
Das Verwenden eines freien Zeigers ist ein nicht definiertes Verhalten.
Zunächst einmal hat Ihr Code UB unabhängig von der Länge der Zeichenfolge: Am Ende von
%Vor% Die von getString
zurückgegebene Zeichenfolge wird gelöscht und castString
ist ein ungeordneter Zeiger auf den internen Puffer des zerstörten Zeichenfolgenobjekts.
Der Grund, warum Ihr Code für kleine Strings "arbeitet", ist wahrscheinlich Small String Optimization: Kurze Strings werden (gewöhnlich) im String-Objekt selbst gespeichert, anstatt in einem dynamisch zugewiesenen Array gespeichert zu werden. Offensichtlich ist der Speicher weiterhin zugänglich und unverändert in deinem Fall.