Crash bei string("text hier")



  • Hi,

    ich parsiere eine xml-Datei mit libxml2. Das funktioniert auch ganz gut.
    Um aus den xmlChar*, die mir die Lib liefert, std::string zu machen, habe
    ich mir folgende Funktion geschrieben.

    string to_str(const xmlChar* xml_string) {
        return result(reinterpret_cast<const char*>(xml_string));
    }
    

    Ich weiß, der Cast ist vielleicht nicht schön, ist aber erstmal ein Platzhalter hier.

    Was jetzt passiert ist, dass irgendwann im x'ten Aufruf (x < 30) dieser Funktion
    der Konstruktor von string eine Exception wirft.

    #0 0x00007ffff6cd3a75 in raise () from /lib/libc.so.6
    #1 0x00007ffff6cd75c0 in abort () from /lib/libc.so.6
    #2 0x00007ffff6d0d4fb in ?? () from /lib/libc.so.6
    #3 0x00007ffff6d175b6 in ?? () from /lib/libc.so.6
    #4 0x00007ffff6d1b8e9 in ?? () from /lib/libc.so.6
    #5 0x00007ffff6d1c58e in malloc () from /lib/libc.so.6
    #6 0x00007ffff758826d in operator new(unsigned long) () from /usr/lib/libstdc++.so.6
    #7 0x00007ffff7564d99 in std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) () from /usr/lib/libstdc++.so.6
    #8 0x00007ffff75658b5 in ?? () from /usr/lib/libstdc++.so.6
    #9 0x00007ffff7565a53 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) () from /usr/lib/libstdc++.so.6
    #10 0x000000000042769d in to_str (xml_string=0x7ffff78e1a40 "text")
    (meine Funktion)

    Es ist in jedem Durchlauf genau dieser Aufruf. Wenn ich den xmlChar* (er ist
    eindeutig) vorher vergleiche und nur in dem Fall string() zurüchliefere, schlägt genau der nächste Aufruf von to_str fehl.

    Offensichtlich kann er keinen Speicher allozieren, aber warum? Soviel verbrauch
    ich nicht, dass der voll sein könnte und malloc / operator new will doch
    auf den Heap?



  • häh?

    char *pchar = "hallo welt";
    std::string test(pchar);
    

    bitte Ressourcen auch wieder freigeben...



  • crashkurs schrieb:

    Ich weiß, der Cast ist vielleicht nicht schön, ist aber erstmal ein Platzhalter hier.

    Geschieht dir recht, wenn solcher Code fehlschlägt 😉

    Warum nicht den Iterator-Konstruktor von std::string nehmen, der die Range zeichenweise kopiert? Dann wird nämlich jedes Zeichen und nicht der Zeiger auf die Zeichenkette gecastet.

    HighLigerBiMBam schrieb:

    bitte Ressourcen auch wieder freigeben...

    Hier gibt es nichts freizugeben.



  • Nicht in meinem Beispiel aber in seinem Code.



  • HighLigerBiMBam schrieb:

    Nicht in meinem Beispiel aber in seinem Code.

    Wo genau? Welchen Fehler macht er? Was soll er tun, um ihn zu vermeiden?
    Selbst ich sehe nicht, welchen Ansatzpunkt Du uns zeigen wolltest oder was Du als Fehlerursache herausgefunden hast.



  • Wo habe ich gesagt das er damit einen Fehler gemacht hat? War nur ein Reminder..



  • Was mir als erstes auffällt: was ist xmlChar? vermutlich KEIN char, oder? Damit übergibst du dem Ctor von std::string eine char-Sequenz die in Wirklichkeit keine ist. Das kann nur in die Hose gehen.



  • crashkurs schrieb:

    string to_str(const xmlChar* xml_string) {
        return result(reinterpret_cast<const char*>(xml_string));
    }
    

    Ja, sieht scheußlich aus. Was weiß man denn über xmlChar ? Erzähl mal.

    crashkurs schrieb:

    Was jetzt passiert ist, dass irgendwann im x'ten Aufruf (x < 30) dieser Funktion
    der Konstruktor von string eine Exception wirft.
    [...]
    Offensichtlich kann er keinen Speicher allozieren, aber warum? Soviel verbrauch
    ich nicht, dass der voll sein könnte und malloc / operator new will doch
    auf den Heap?

    Tja. Kann man -- aufgrund der wenigen Informationen -- nur raten. Auch wenn ich eine Idee habe, woran es liegen könnte, würd ich mir von Dir doch lieber erst erklären lassen, was xmlChar sein soll.



  • So what is this funky "xmlChar" used all the time?
    It is a null terminated sequence of utf-8 characters. And only utf-8! You need to convert strings encoded in different ways to utf-8 before passing them to the API. This can be accomplished with the iconv library for instance.

    Ich kann garantieren, dass in der parsierten xml nur ASCII-Subset von utf-8 ist.

    Geschieht dir recht, wenn solcher Code fehlschlägt 😉

    Ich weiß, ich weiß. Ich habe aber bevor ich gefragt habe, folgendes probiert:
    Genau den Konstruktoraufruf, der immer auf die Bretter geht, durch
    eine If-Anweisung ausklammern und stattdessen return string("peterpan").
    Gleicher Fehler. Ich dachte daher, dass es zumindest nicht am cast liegt.

    Warum nicht den Iterator-Konstruktor von std::string nehmen, der die Range zeichenweise kopiert? Dann wird nämlich jedes Zeichen und nicht der Zeiger auf die Zeichenkette gecastet.

    Kopiert nicht string(const char*) auch den Speicherbereich?

    Danke schon mal für die vielen Antworten.



  • Kannst du mal ein vollständig funktionierendes Beispiel schrieben, dass den Fehler reproduziert?



  • Crashkurs schrieb:

    Ich habe aber bevor ich gefragt habe, folgendes probiert:
    Genau den Konstruktoraufruf, der immer auf die Bretter geht, durch
    eine If-Anweisung ausklammern und stattdessen return string("peterpan").
    Gleicher Fehler.

    Du hast dir möglicherweise schon vorher den Heap zerlegt.



  • MFK schrieb:

    Du hast dir möglicherweise schon vorher den Heap zerlegt.

    Jup. Sieht sehr danach aus.
    Vorgehen: reduziere den Code immer weiter, vor allem die Aufrufe davor sollten soweit möglich auskommentiert werden und Schritt für Schritt durch dummies ersetzt werden. Sobald der Fehler verschwindet hast du den Code auskommentiert, der den Fehler verursacht (hoffentlich).



  • Danke für eure Hinweise. Ich schau mal.


Log in to reply