Rückgabe des Strings bei Exception: Korrekt?
-
catch(...) ist nicht wirklich sauberer ...
Dennoch finde ich den Hinweis auf eine möglich exception von c_str() hilfreich.
Wobei es fraglich ist ob und wie man vernünftig,
auf z.B. std::bad_alloc reagieren soll.Das Programm zu beenden ist da nicht die schlechteste aller Strategien ...
Gruß Frank
-
[quote="seldon"]Theoretisch kann c_str() allerdings eine Exception werfen (beispielsweise std::bad_alloc), was wegen des throw()-Specifiers von what() zum Aufruf von std::unexpected führen würde.
[quote]
Wie kann c_str() eine Exception werfen?
std::string beinhaltet intern einen char*. Und c_str() macht ja nichts anderes als diesen char* in ein const char* zurückzugeben.Verstehe ich da was falsch?

-
Frank Erdorf schrieb:
Dennoch finde ich den Hinweis auf eine möglich exception von c_str() hilfreich.
falls er denn stimmen sollte...
Generell schließe ich mich ÄhhhWTF?! an
Wo hast du die Info denn her?
http://www.cplusplus.com/reference/string/string/c_str/
Hier sehe ich auch keinen Hinweis auf eine potentielle Exception
-
std::string beinhaltet intern einen char*. Und c_str() macht ja nichts anderes als diesen char* in ein const char* zurückzugeben.
So ist es warscheinlich implementiert, aber es ist nicht so festgelegt!
Ich habe es auch schon mal so angenommen und unter 5 Kompilern keine Probleme gehabt - was nich bedeutet das auch IMMER so ist.
Gruß Frank
-
In vielen Implementationen ist das so, aber es ist vom Standard nicht zwingend vorgegeben und auch nicht überall der Fall; c_str() wird dort sogar explizit als eine der Funktionen genannt, die den internen Status eines Strings verändern dürfen (wodurch Zeiger, Referenzen und Iteratoren auf seine Interna invalidiert werden).
Etwa könnte ein std::string auf den Sentinel verzichten, bis c_str() zum ersten mal aufgerufen wird - beispielsweise bei Blockbehandlung, wenn Paging eine Rolle spielt (std::string ist nicht nullterminiert) oder zum Speichersparen bei kurzen Strings. Oder er könnte im Backend eine deque benutzen, um Anhängen/Abhängen an beiden Enden schneller zu machen - std::string garantiert nicht, dass seine Daten in einem zusammenhängenden Speicherstück liegen. Oder es könnte bei einer referenzzählenden Implementation (diese Möglichkeit wird im Standard explizit benannt) Gründe geben, sich beim Aufruf von c_str() aus dem gemeinsamen Datenpool zu lösen.
Meistens wird das wohl nicht gemacht, aber der Standard gibt für c_str() keine nothrow-Garantie, um den Bibliotheksentwicklern Freiräume zu lassen. Und man sollte davon ausgehen, dass ein moderner Compiler den Try-Block, wenn er nachweisen kann, dass c_str() nicht wirft, eh wegoptimiert.
-
Frank Erdorf schrieb:
std::string beinhaltet intern einen char*. Und c_str() macht ja nichts anderes als diesen char* in ein const char* zurückzugeben.
So ist es warscheinlich implementiert, aber es ist nicht so festgelegt!
Ich habe es auch schon mal so angenommen und unter 5 Kompilern keine Probleme gehabt - was nich bedeutet das auch IMMER so ist.
Gruß Frank
§17.4.4.8/3: "Any other function [than destructors] defined in the
C++ Standard Library that do not have an exception-specification may
throw implementation-defined exceptions unless otherwise specifiedOkay...
Für mich persönlich wird diese Tatsache allerdings nichts an meinem
Programmierverhalten ändern...
-
Schreib dir halt ne Funktionsvorlage
template<typename string_type> char const *c_str_nothrow(string_type const &s) throw() { char const *p = "Fehler beim Holen der Fehlermeldung"; // o.ä. try { p = s.c_str(); } catch(...) { } return p; }und in der Exception
virtual char const *what() const throw() { return c_str_nothrow(m_message); }Das sollte ja nun wirklich beherrschbar sein.
-
CSpille schrieb:
Okay...
Für mich persönlich wird diese Tatsache allerdings nichts an meinem
Programmierverhalten ändern...Gleichfalls, trotzdem nett zu wissen. An dieser Stelle bedanke ich mich!

-
seldon schrieb:
Das sollte ja nun wirklich beherrschbar sein.
Hast du absolut recht...
Allerdings werde ich grundsätzlich nicht meinen Programmiercode
für irgendwelche Wurst-Compiler anpassen.Mir reicht es, wenn mein Code auf dem gcc compiliert, denn
den gibt es notfalls auch für fast alle gängigen Plattformen.Als Beispiel:
Ich verwende 0 statt NULL.
Wenn irgendein Wurst-Compiler jetzt 0xdeadbeef als NULL verwendet,
würden alle if(ptr) in die Hose gehen.
Aber ehrlich gesagt ist mir das s*** egal...
-
Exception Specifications zu verwenden ist generell etwas fragwürdig (unabhängig vom Beispiel hier).
http://www.gotw.ca/publications/mill22.htm