Boost.PropertyTree Problem mit std::ends
-
Hi
Arbeite grad mit Boost.PropertyTree und da ist mir folgendes aufgefallen:
#include <iostream> #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/xml_parser.hpp> int main() { std::stringstream ss; ss << "example"; boost::property_tree::ptree pTree; read_xml( "example.xml", pTree ); try { std::cout << pTree.get< std::string >( ss.str().c_str() ); //fine std::cout << pTree.get< std::string >( ss.str() ); //fine ss << std::ends; std::cout << pTree.get< std::string >( ss.str().c_str() ); //fine std::cout << pTree.get< std::string >( ss.str() ); //crash! }catch( std::exception &e ) { std::cout << e.what(); } return 0; }erzeugt mit folgender XML-Datei:
<?xml version="1.0" encoding="utf-8" ?> <example>text</example>folgende Ausgabe:
texttexttextNo such node(example)Folgenden Exception wird geworfen:
boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::property_tree::ptree_bad_path> > at memory location 0x0014f064..Getestet unter Visual Studio 2008 & 2010 mit Boost 1.42.
Hab versucht dem Problem auf den Grund zu gehen aber das sind ein halbes dutzend Dateien die man da debuggen muss.Koennt ihr den Fehler reproduzieren?
Dass std::ends der Auslöser ist dürfte wohl klar sein, die Frage ist ob std::ends einfach böse ist oder ob Boost.PropertyTree einen Fehler hat.
Bitte um eure Kommentare
-
http://www.cplusplus.com/reference/iostream/manipulators/ends/
Willst du das denn wirklich?
-
Der Sachverhalt ist relaitv simpel. Ich habs jetzt nicht genau nachgeschaut, vermute aber einfach mal, dass ptree::path_type std::string ist.
der std::string, der hinter dem stringstream steht, heißt "example" und hat die Länge 7. Zu deinen 4 Aufrufen:
try { std::cout << pTree.get< std::string >( ss.str().c_str() ); // 1 std::cout << pTree.get< std::string >( ss.str() ); // 2 ss << std::ends; std::cout << pTree.get< std::string >( ss.str().c_str() ); // 3 std::cout << pTree.get< std::string >( ss.str() ); // 4 }get() mit einem Parameter erwartet einen path_type, also einen std::string. Im Aufruf 1 lieferst du einen const char*, die Sequenz ist {'e','x','a','m','p','l','e','\0'}, wobei das '\0' von c_str() angehängt wurde. Daraus wird ein std::string gebaut, der wiederum "example" als Inhalt und die Länge 7 hat.
In Aufruf 2 wird der ursprüngliche std::string genommen, hat also auch die Länge 7.danach packst du ein ends, also ein '\0' in den Stream. Der zugrundeliegende std::string hat die Länge 8(!) und den Inhalt "example\0".
Aufruf 3: es wird ein const char* übergeben, die Sequenz ist {'e','x','a','m','p','l','e','\0','\0'}. Daraus wird wiederum ein std::string gebastelt, der beim ersten '\0' aufhört und deshalb die Länge 7 und Inhalt "example" hat, also kein Problem.
Aufruf 4: es wird der std:.string mit Länge 8 und dem nullcharacter übergeben, beim Parsen fliegt das Framework völlig zu Recht auf die Nase - Nullcharacter sind in XML-Pfaden nunmal nicht vorgesehen.
-
Danke für die Aufklärung. Die Idee mit std::ends ist nicht auf meinem Mist gewachsen. Das wird in dem Code den ich gerade bearbeite wie folgt genutzt:
//-------------------------------------------------------------------------------- // This function is used to clear a stringstream in an efficient way, // maintaining the internal buffer as described here: // http://stackoverflow.com/questions/624260/how-to-reuse-an-ostringstream/624291#624291 //-------------------------------------------------------------------------------- inline void clearStrStream( std::wstringstream &stream ) { stream.clear(); stream.seekg( 0 ); stream.seekp( 0 ); } //-------------------------------------------------------------------------------- ... std::wstringstream wStrStream( L"dummy" ); for(...) { //Reuse stringstream clearStrStream( wStrStream ); ... }Das hat mein Vorgänger wohl nie getestet

-
rean schrieb:
Danke für die Aufklärung. Die Idee mit std::ends ist nicht auf meinem Mist gewachsen. Das wird in dem Code den ich gerade bearbeite wie folgt genutzt:
...Das hat mein Vorgänger wohl nie getestet

Da wird nirgendwo ends benutzt. Das ends steht nur irgendwo auf der verlinkten Seite, wo dein Kollege die "clearStrStream"-Funktion her hat.