Mir Unerklärliches Signal11/SegmentationFault
-
Momentan hänge ich gerade in meinem Programm an einem Problem:
Das Programm beendet sich mit einem Signal11.
Der Debugger meint, das Signal tritt beim verlassen eines if(){} - Blocks auf. Das seltsame: In diesem if(){} - Block gibt es nur eine Zuweisung an einen Pointer, und dieser ist auch noch bereits im Darüberliegenden Block der Funktion deklariert und ein weiterer if(){} - Block wird aufgerufen.Jetzt sagt mir mein C++ - Verständniss, das das Signal11 eigentlich nur daher stammen kann, dass ein Objekt, dass innerhalb des Blocks auf dem Stack erstellt wurde im Destruktor einen NULL-Pointer mit delete vernichtet, was hier ja eigentlich nicht der fall sein kann.
Wenn jemand sich den Funktionscode antun möchte (TinyXML & gtkmm):
http://christoph.sf-ogame.de/Entwicklung/bsp.cppIn kürze:
void WD::make_parse(std::string to_parse) { TiXmlDocument doc; doc.Parse(to_parse.c_str()); TiXmlNode * node, * node2; TiXmlElement * element, * element2, * element3; std::stringstream tmp; [...] node = doc.FirstChild("strength"); if (node) { element = node->ToElement(); if (element) { [...] } }// Hier tritt der Segfault auf }
Was _kann_ hier schiefgehen / was könnte ich testen?
EDIT://
Callstack:
#0 0xb7227e07 free() (/lib/tls/i686/cmov/libc.so.6:??) #1 0xb73e5d11 operator delete() (/usr/lib/libstdc++.so.6:??) #2 0xb73c2a5d std::string::_Rep::_M_destroy() (/usr/lib/libstdc++.so.6:??) #3 0xb73c55e7 std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (/usr/lib/libstdc++.so.6:??) #4 0x805ae2d ~TiXmlDocument(this=0xbfb6025c) (/home/darthdespotism/dev/Editor/Editor/tinyxml.h:1375) #5 0x806c492 param::WD::make_parse(this=0x80d3158, to_parse=@0xbfb60360) (/home/darthdespotism/dev/Editor/Editor/ed_param.cpp:439) #6 0x806d635 param::WD::on_ac_mi_open(this=0x80d3158) (/home/darthdespotism/dev/Editor/Editor/ed_param.cpp:121) #7 0x8072be1 sigc::bound_mem_functor0<void, param::WD>::operator() (this=0x8240d7c) (/usr/include/sigc++-2.0/sigc++/functors/mem_fun.h:1787) #8 0x8072bf8 sigc::adaptor_functor<sigc::bound_mem_functor0<void, param::WD> >::operator() (this=0x8240d78) (/usr/include/sigc++-2.0/sigc++/adaptors/adaptor_trait.h:251) #9 0x8072c14 sigc::internal::slot_call0<sigc::bound_mem_functor0<void, param::WD>, void>::call_it(rep=0x8240d60) (/usr/include/sigc++-2.0/sigc++/functors/slot.h:103) #10 0xb77fa33a Glib::SignalProxyNormal::slot0_void_callback() (/usr/lib/libglibmm-2.4.so.1:??) #11 0xb74d89d9 g_cclosure_marshal_VOID__VOID() (/usr/lib/libgobject-2.0.so.0:??) #12 0xb74cb62b g_closure_invoke() (/usr/lib/libgobject-2.0.so.0:??) #13 0xb74dc3f1 ??() (/usr/lib/libgobject-2.0.so.0:??) #14 0x8240da8 ??() (??:??) #15 ( ??() (??:??)
Disassembly:
0xb7227df5 lea esi,[ebx+0x112c] 0xb7227dfb je 0xb7227e09 <free+105> 0xb7227dfd and DWORD PTR [ebp-28],0xfff00000 0xb7227e04 mov eax,DWORD PTR [ebp-28] 0xb7227e07 mov esi,DWORD PTR [eax] 0xb7227e09 xor eax,eax 0xb7227e0b mov ecx,0x1 0xb7227e10 cmp DWORD PTR gs:0xc,0x0 0xb7227e18 je 0xb7227e1b <free+123> 0xb7227e1a lock cmpxchg DWORD PTR [esi],ecx 0xb7227e1e jne 0xb72288f7 <_fini+1179475>
-
vom callstack her fühlt es sich so an als ob 2mal deleted wird.
ich vermute mal es hat was mit to_parse und doc zu tun.
-
Um genau zu sein müsste das Signal auch beim verlassen der Funktion aufgetreten sein, da die innerhalb der Funktion globale Variable TiXMLDocument zerstört wird.
Anderer Punkt: Ist es möglich das der Bug in TinyXML liegt? immerhin ist das deren destruktor wenn ich das recht sehe.
Allerdings habe ich garantiert weniger Erfahrung als die Leute von TinyXML
-
tixmldocument ist doch nicht global, sondern funktionslokal,
und ja sie wird beim verlassen dieser funktion zerstört.weiters wär interessant zu schauen was genau in tinyxml.h zeile 1375 dort zerstört wird.
#4 0x805ae2d ~TiXmlDocument(this=0xbfb6025c) (/home/darthdespotism/dev/Editor/Editor/tinyxml.h:1375)
schonmal probiert to_parse als const referenz zu übergeben ?
void WD::make_parse(std::string const& to_parse)
-
jop das Document ist nicht global, aber im "globalen", größten Block der funktion und nach meinen debuggerergebnissen wird es schon vor verlassen der funktion zerstört.
TinyXML.h Zeile 1375:
virtual ~TiXmlDocument() {}
-
Mach bitte mal in Zeile 23 eine Testausschrift.
Aus dem Stacktrace ist deutlich ersichtich dass gerade ~TiXmlDocument destruiert wird; also knallt's bei der letzten schliessenden Klammer - für die vorletzte sollte gar keinen Code erzeugt werden.
Das liest sich sonst ja rcht einfach; es knallt bei der Freigabe des internen Puffers eines std::string in ~TiXmlDocument.
Derweiteren wird offenbar ein free für Thread-local-Storage aufgerufen (../tls/..); für mich siehrt das so aus als würde tls Memory "freed" das gar keines ist, oder das TLS-Segmant sei nicht korekt initialisiert worden.
Fehlt da vielleicht irgendein init() für die TinyXML-RT ?Grüsse
*this
P.S.: Das "lock" im Disassembly ist mir etwas suspekt; hast Du ein MP-System oder kompilierst Du nur mit MP-Einstellungen?
-
Als Arbeitshypothese würde ich davon ausgehen, dass TiXmlDocument, basic_string, free etc. bug-frei sind. Dann können wir schlussfolgern, dass irgendwann nach der Erzeugung von doc, etwas schiefläuft und entweder das doc Objekt oder der darin enthaltene string oder der heap selbst durch fehlerhafte Zugriffe verändert werden. Die entsprechende Stelle kriegt man durch breakpoints und Untersuchung der Daten heraus.
-
camper schrieb:
Als Arbeitshypothese würde ich davon ausgehen, dass TiXmlDocument, basic_string, free etc. bug-frei sind.
Stört Dich das "tls" nicht ?
Ist das normal beim g++?Grüsse
*this
P.S.: Hab hier grad kein *nix; deshalb frag ich so doof
-
Gast++ schrieb:
P.S.: Das "lock" im Disassembly ist mir etwas suspekt; hast Du ein MP-System oder kompilierst Du nur mit MP-Einstellungen?
Das System ist tatsächlich SMP (C2D)
Und noch was ist mir aufgefallen, kann ich aber noch nicht unbedingt bestätigen:
Mit dem g++ 4.1.2 habe ich das Problem mit dem MinGW-Crosscompiler (3.4?) scheint der Code zu laufen, kann ich aber nicht sicher sagen, da ich kein Win zur Hand habe und GTK+ mit Wine nicht so recht funktioniert.camper schrieb:
Als Arbeitshypothese würde ich davon ausgehen, dass TiXmlDocument, basic_string, free etc. bug-frei sind. Dann können wir schlussfolgern, dass irgendwann nach der Erzeugung von doc, etwas schiefläuft und entweder das doc Objekt oder der darin enthaltene string oder der heap selbst durch fehlerhafte Zugriffe verändert werden. Die entsprechende Stelle kriegt man durch breakpoints und Untersuchung der Daten heraus.
Alles andere wäre ja auch weltfremd.
Was genau meinst du mit den Breakpoints? Mit den Debuggern habe ich noch nicht so viel erfahrung. (Und ich habe aus meinen Brekpoints darauf geschlossen dass er beim Verlassen des if(){} Segvaulted, was eindeutig wiederlegt ist IMHOEDIT://
Ich sehe gerade dass andere, garantiert unveränderte Programmteile beim Selben Vorgang auch Segvaullten, die auf meinem SingleCore Desktoprechner sowohl mit ubuntu/linux, wie hier auf dem Notebook, als auch unter Win problemfrei liefen.Gut möglich dass da etwas nicht threadsafe ist. Weiß jemand wie ich das dem g++ abgewöhne (ich habe nie explizit threads verwendet in diesem Programm)
-
Gib doch mal dem gcc/g++ ein -v mit und poste nur den kompletten Aufruf des Compilers für die Datei und den des Linkers.
(z.B.make 2>&1 | tee -a mylog.txt)Über das "tls"-free komm ich irgendwie nicht hinweg!
Grüsse
*this
-
Ok dann wirds wohl auf die Commandline gehen. C::B gibt da wohl nicht die daten zu raus.
EDIT://
Ergebniss:Commandline:
g++ -v dlgs.cpp ed_kamp.cpp ed_param.cpp ed_ship.cpp ed-wave.cpp main.cpp tinyxml.cpp tinyxmlerror.cpp tinyxmlparser.cpp tinystr.cpp `pkg-config gtkmm-2.4 --cflags --libs` -I/usr/include/libglademm-2.4 -lglademm-2.4
Ergebniss:
Auf der Kommandline
-
darthdespotism schrieb:
Ok dann wirds wohl auf die Commandline gehen. C::B gibt da wohl nicht die daten zu raus.
Wir müssen exakt die gleiche Konfig haben
=> Makefile exportieren
=> -g setzen EDIT : -v war gemeint!!! /EDIT
=> Absturz MIT DER NEUEN EXE reproduzieren!!!Grüsse
*this
-
also der Fehler ist reproduzierbar. Die Option makefiles zu exportieren hab ich schonmal vergeblich in C::B gesucht.
-
darthdespotism schrieb:
also der Fehler ist reproduzierbar. Die Option makefiles zu exportieren hab ich schonmal vergeblich in C::B gesucht.
Wnn im Manager das Projekt selktiert ist:
"Build" => "Export Makefile"
???
Finde bitte mal gleich crt*.o unterhalb von /lib/tls
Grüsse
*this
-
Gast++ schrieb:
"Build" => "Export Makefile"
Die Option ist vorhanden aber leider ausgegraut. Projekt ist ativ und selektiert.
Was mache ich mit den crt*.o wenn ich sie gefunden habe?
/lib/tls enthält _nur_ den Ordner i686 welcher wiederum nur cmov enthält. Darin gibts dann einige Dateien, aber keine einzige beginnt mit crt
-
darthdespotism schrieb:
Gast++ schrieb:
"Build" => "Export Makefile"
Die Option ist vorhanden aber leider ausgegraut. Projekt ist ativ und selektiert.
??? => IDE Forum !
darthdespotism schrieb:
Was mache ich mit den crt*.o wenn ich sie gefunden habe?
Die Ausgabe posten...
Grüsse
*this
-
darthdespotism@akazieLX:~/dev/Editor/Editor$ ls /lib/tls/ i686
darthdespotism@akazieLX:~/dev/Editor/Editor$ ls /lib/tls/i686 cmov
darthdespotism@akazieLX:~/dev/Editor/Editor$ ls /lib/tls/i686/cmov ld-2.5.so libcrypt-2.5.so libnsl.so.1 libnss_nis-2.5.so librt-2.5.so ld-linux.so.2 libcrypt.so.1 libnss_compat-2.5.so libnss_nisplus-2.5.so librt.so.1 libanl-2.5.so libc.so.6 libnss_compat.so.2 libnss_nisplus.so.2 libSegFault.so libanl.so.1 libdl-2.5.so libnss_dns-2.5.so libnss_nis.so.2 libthread_db-1.0.so libBrokenLocale-2.5.so libdl.so.2 libnss_dns.so.2 libpcprofile.so libthread_db.so.1 libBrokenLocale.so.1 libm-2.5.so libnss_files-2.5.so libpthread-2.5.so libutil-2.5.so libc-2.5.so libmemusage.so libnss_files.so.2 libpthread.so.0 libutil.so.1 libcidn-2.5.so libm.so.6 libnss_hesiod-2.5.so libresolv-2.5.so libcidn.so.1 libnsl-2.5.so libnss_hesiod.so.2 libresolv.so.2
Keinerlei crt*.o
Gast++ schrieb:
??? => IDE Forum !
http://www.c-plusplus.net/forum/viewtopic-var-p-is-1287956.html#1287956 OK?
-
Ich meinte zwar einen richtigen "find"; keinen ls ; aber wo ich grad eine libc.co.6 sehe:
https://bugs.launchpad.net/ubuntu/+source/gawk/+bug/58256
Schau Dir mal den Stacktrace an; da knallts auch in der tls-version von free()!
Das Problem steht dort zwar als "fixed" aber wo sich der Fix nun befindet entzieht sich meiner Kenntnis.
Es gäbe vielleicht die Möglichkeit TinyXML ohne STL Nutzung zu kompilieren; im Makefile von TinyXML
TINYXML_USE_STL := NO
setzen.
Wenn ich die Ubuntu-Seite richtig verstehe müsste es eigentlich bei jedem delete eines leeren std::string knallen; Knallt's denn auch wenn Du selber einen leeren lokalen std::string verwendest?
Falls ja könntest Du das vielleicht mit einem eigenen Allokator bekämpfen.Aber ich kann imnmer noch nicht glauben dass man dem g++ nicht das tls abgewöhnen kann ; allerdings seh ich in Deinen Compilerschaltern nichts Einschlägiges.
Grüsse
*this
-
Ich kann TinyXML das Verwenden der STL abgewönen indem ich vor dem Inkludieren ein Makro nicht definiere. Meine ich schonmal verscuht zu haben aber ich probiers nochmal. Ebenso das mit dem leeren string.
#include <string> int main() { std::string test; }
funktioniert genauso wie
#include <string> int main() { std::string test; test = ""; }
EDIT://
Wenn ich TinyXML OHNE std::string verwende (kein #define TIXML_USE_STL) funktioniert das tatsächlich.
-
[quote="darthdespotism"]
#include <string> int main() { std::string test; }
Das würde ich aber in der Methode machen wo der Fehler auftritt EDIT und zwar in einem eigen Block /EDIT; so wie ich den Stacktrace deute wird die Funktion von einem Framework(Thread) aufgerufen!
Grüsse
*this