Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » std::string::c_str()

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
02.07.2010, 23:44 Uhr
Lensflare



Hallo

ich habe wieder eine Frage zum richtigen Umgang mit C strings.

Da in meinem Programm viele Strings zur Laufzeit erstellt werden, benutze ich den std::stringstream und wandle den Inhalt dann in ein std::string.

Leider verlangt der Filestream "std::ifstream" für das Öffnen der Datei einen C String:

C++:
void open ( const char * filename, ios_base::openmode mode = ios_base::in );


Das heisst dann, dass ich meinen std::string mit "string::c_str()" in einen C String umwandeln muss.

Auf dieser Seite
www.cplusplus.com/reference/string/string/c_str/
steht dass der Pointer, der von c_str() zurückgegeben wird, auf den Inhalt des std::strings verweist.

Jetzt stellt sich für mich die Frage, ob ich den C String (also das, auf was der pointer zeigt) manuell freigeben muss, sobald der std::string gelöscht ist.
Oder wird der Inhalt von std::string automatisch freigegeben?

Beide Möglichkeiten haben unterschiedliche Folgen, auf die ich achten müsste.
--
Wenn das Gehirn so einfach wäre, dass wir es verstehen könnten, wären wir so einfach, dass wir es nicht verstehen könnten.
(Emerson Pugh Trost)

Dieser Post wurde am 02.07.2010 um 23:46 Uhr von Lensflare editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
03.07.2010, 03:09 Uhr
Blubber2063



Die Seite gibt dir die Antwort:

The returned array points to an internal location with the required storage space for this sequence of characters plus its terminating null-character, but the values in this array should not be modified in the program and are only granted to remain unchanged until the next call to a non-constant member function of the string object.

Klartext, die Funktion gibt einen const char* zurück, d.h. du kannst den Inhalt nicht ändern und außerdem steht dort internal location, also speicher der von der string Klasse verwaltet wird. Und das der Zugriff auf das Ergebnis nur bis zum nächsten non const call gültig ist. Insbesondere dann wenn das Objekt zerstört wird solltest du nicht mehr auf das Ergebnis zugreifen.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
03.07.2010, 22:49 Uhr
Lensflare



Bist du dir sicher?

Ich habe das mit der internal location auch so verstanden, aber da steht ja nicht direkt drin, dass diese interne location auch aufgeräumt wird.

Vielleicht wollte der designer dieser klasse auf diese weise verhindern, dass nach der zerstörung des std::string objekts weiterhin auf freigegebenen speicher zugegriffen wird.

Diese C Strings sind echt eine Plage. Wenn funktionen c strings als parameter verlangen und dieser string zur laufzeit erstellt werden muss, dann muss ich entweder sicherstellen, dass der string aufgeräumt wird, wenn diese funktion ihn nicht mehr braucht (und das weiss man ja nicht immer so genau) oder ich muss sicherstellen dass die funktion nicht irgendwann auf den string versucht zuzugreifen und dieser wurde schon freigegeben.
Kann man da evtl was mit smart pointern machen um diesem problem auf dem weg zu gehen?

Das mag jetzt ein generelles Problem sein, dass jede art von dynamischem speicher betrifft, aber mit anderen daten hatte ich nie wirklich probleme damit. Bei c strings ist es so eine sache, die wandern oft quer durch alle strukturen durch oder werden an eine funktion einer library übergeben und man weiss nicht was aus ihnen wird und wann sie nicht mehr gebraucht werden.

Für den konkreten Fall, dass ich den std::ifstream verwende:
Muss ich also dafür sorgen, dass der std::string so lange bestehen bleibt, bis der filestream mit seiner arbeit fertig ist? Ich übergebe dem filestream ja einen pointer auf den internen bereich des std::string.
Wenn du recht hast, dann wäre die antwort wohl ja, nehme ich an.
--
Wenn das Gehirn so einfach wäre, dass wir es verstehen könnten, wären wir so einfach, dass wir es nicht verstehen könnten.
(Emerson Pugh Trost)

Dieser Post wurde am 03.07.2010 um 22:51 Uhr von Lensflare editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
04.07.2010, 00:39 Uhr
0xdeadbeef
Gott
(Operator)


Im konkreten Fall muss der string beim Aufruf von open (oder des Konstruktors) gültig sein. Danach wird er nicht mehr gebraucht. std::string::c_str() gibt einen Speicherbereich zurück, der der betreffenden Instanz von std::string gehört und um den diese sich zu kümmern hat; das heißt, dass der Speicherbereich ungültig wird, sobald die Instanz zerstört wird.

Zusätzlich kann er ungültig werden wie folgt:

Zitat von ISO/IEC 14882:2003 13.2 (5):

References, pointers, and iterators referring to the elements of a basic_string sequence may be invalidated by the following uses of that basic_string object:

— As an argument to non-member functions swap() (21.3.7.8), operator>>() (21.3.7.9), and getline() (21.3.7.9).
— As an argument to basic_string::swap().
— Calling data() and c_str() member functions.
— Calling non-const member functions, except operator[](), at(), begin(), rbegin(), end(), and rend().
— Subsequent to any of the above uses except the forms of insert() and erase() which return iterators, the first call to non-const member functions operator[](), at(), begin(), rbegin(), end(), or rend().


Letzteres ist im Zusammenhang mit referenzzählenden Implementationen wichtig.

Beispiele:

C++:
std::string s = "foo";
char const *p = s.c_str();

s.clear();

// p ist jetzt ungültig.


Das war ziemlich offensichtlich. Weniger offensichtlich (und wohl auch eher selten tatsächlich explosiv):

C++:
std::string s = foo;
char const *p = s.c_str();
char const *q = s.c_str();

// p ist jetzt ungültig.


Außerdem:

C++:
std::string s = "foo";

char const *p = s.c_str();
s[0] = 'h';

// p jetzt ungültig.


Der Hintergrund hierfür ist, dass std::string nicht nullterminiert sein muss. (!) c_str() muss lediglich einen Speicherbereich organisieren, der dem Inhalt des Strings zum Aufrufszeitpunkt entspricht; dieser muss nicht mit dem ursprünglichen Datenbereich übereinstimmen (deswegen auch die Unterscheidung zwischen c_str() und data()). Der std::string darf in diesem Moment auch seinen Datenbereich umschichten und einen Sentinel anhängen, oder beispielsweise eine Sonderbehandlung für leere Strings machen, um etwa heap contention zu vermeiden.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 04.07.2010 um 00:47 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
04.07.2010, 01:05 Uhr
Lensflare



ok danke. das hat sich dann geklärt.

Aber warum verlangt eine funktion aus der standard c++ lib (wie zB der std::ifstream) nicht gleich einen std::string?
--
Wenn das Gehirn so einfach wäre, dass wir es verstehen könnten, wären wir so einfach, dass wir es nicht verstehen könnten.
(Emerson Pugh Trost)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
04.07.2010, 02:00 Uhr
0xdeadbeef
Gott
(Operator)


Naja, man könnte da jetzt was von Performanceoptimierung herfaseln (nicht den Heap zu bemühen, bloß um nachher doch einen C-String aus dem std::string zu ziehen und in fopen zu schmeißen), aber vermutlich ist das schlicht historisch gewachsen. Standardisierung ist zum großen Teil deskriptiv, will sagen, es wird das, was sowieso von allen gemacht wird, in einen Standard gegossen.

Ich nehme an, dass std::string in der Evolution von C++ relativ spät Einzug fand, insbesondere nach std:io)fstream, und dementsprechend gängige iostream-Implementationen char const* benutzten. Zumal ja in den Anfängen vieles nicht bekannt war, was sich später an Praktiken entwickelte - beispielsweise war Template-Metaprogrammierung noch gar nicht absehbar.

Wenn du das aber genau wissen willst, musst du dich an das betreffende ISO-Komitee wenden.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: