Creating a Backtrace with GDB/de
│
Deutsch (de) │
English (en) │
日本語 (ja) │
русский (ru) │
Gründe für das Erstellen einer Ablaufverfolgung
Fehlerberichte
Ablaufverfolgungen können nützlich sein, wenn sie Fehlerberichte (Bug Reports) einreichen. Sie werden ohne Zweifel die Chancen erhöhen, dass der Fehler früher berichtigt wird.
Hilft ihnen selbst ein Problem zu finden
Eine Ablaufverfolgung kann wirklich die Mühe herausnehmen, ein Problem mit ihrem eigenen Programm zu finden. Sie deckt das Problem oft unverzüglich auf.
Einfach nur Spaß!!
Okay dies mag eine Ausdehnung sein, aber erstellen von Ablaufverfolgungen ist einfach nur Spaß!
Im Ernst, wenn ihnen ein anderer Grund einfällt für die Erstellung einer Ablaufverfolgung, dann fügen sie ihn hier hinzu.
Erstellen einer Ablaufverfolgung
Um eine Ablaufverfolgung zu erstellen mit GDB (Gnu DeBugger):
- Sie müssen das Programm GDB haben. Es ist verfügbar in den meisten *nix Installationen. Wenn sie die Windows Version von FPC oder Lazarus downgeloadet haben, ist GDB bereits in der Installation enthalten. In Lazarus ist es als Vorgabe Debugger eingestellt. Schauen sie unter Werkzeuge -> Einstellungen -> Debugger -> Allgemein nach. Der Vorgabepfad unter Windows ist c:\lazarus\mingw\bin\gdb.exe.
- GDB muss in der PATH Umgebungsvariablen sein. Wenn es das nicht ist, tippen sie in der Kommandozeile (Beispiel): set PATH=%PATH%;c:\lazarus\mingw\bin\
- Das Programm, welches sie debuggen wollen, MUSS die Debugging Information in der *.exe Datei enthalten. Wenn sie "strip" oder "upx" benutzt haben, mit "Xs" kompiliert haben oder einige andere exe shrinker/compressor benutzt haben, wird es nicht funktionieren!
Windows Benutzer:
1. Öffnen sie eine MS-DOS Eingabeaufforderung
2. Wechseln sie zum Laufwerk, wo sich ihre exe befindet:
C: {Enter drücken}
3. Wechseln sie zum Verzeichnis, das die exe enthält:
cd \myprograms\Project1 {Enter drücken}
Linux/BSD Benutzer:
1. Öffnen sie ihr bevorzugtes Terminal Programm
2. Wechseln sie zum Verzeichnis, das die exe enthält:
cd $HOME/myprograms/project1 {Enter drücken}
Laden sie ihr Programm mit GDB:
gdb Project1.exe {Enter drücken}
Sie sollten eine Kommandozeile sehen, die in etwa so aussieht:
GNU gdb 6.3.50.20050217-cvs Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i686-pc-linux-gnu". (gdb) _
Nun, starten sie ihr Programm:
run {Enter drücken}
Ihr Programm wird normal laufen, bis es abstürzt oder einen Fehler verursacht.
Wenn ihr Programm abstürzt anstelle der üblichen Fehler "Zugriffsverletzung" oder "Division durch Null", scheint ihr Programm zu stoppen, reagiert nicht und zeichnet sich selbst nicht neu. Dies ist so, weil GDB den Fehler erwischt hat und auf sie wartet, um zu sagen, was zu tun ist.
Wechseln sie zu ihrem MS-DOS Fenster oder Terminal und sie sollten einen Bildschirm haben wie diesen:
Program received signal SIGFPE, Arithmetic exception. 0x080733aa in TFORM1__BUTTON1CLICK (SENDER=0x403d8bd8, this=0x403d77d8) at unit1.pas:36 Current language: auto; currently pascal (gdb) _
Um eine Ablaufverfolgung zu erstellen tippen sie jetzt:
backtrace {Enter drücken}
oder
bt {Enter drücken}
Sie sollten jetzt einen Bildschirminhalt haben, der ähnlich wie dieser aussieht:
#0 0x080733aa in TFORM1__BUTTON1CLICK (SENDER=0x403d8bd8, this=0x403d77d8) at unit1.pas:36 #1 0x080ecd78 in TCONTROL__CLICK (this=0x403d8bd8) at control.inc:1768 #2 0x081274bd in TBUTTONCONTROL__CLICK (this=0x403d8bd8) at buttoncontrol.inc:57 #3 0x08129171 in TCUSTOMBUTTON__CLICK (this=0x403d8bd8) at buttons.inc:186 #4 0x08129198 in TCUSTOMBUTTON__WMDEFAULTCLICKED (MESSAGE={MSG = 1031, WPARAM = 136821192, LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, WPARAMHI = 2087, LPARAMLO = 59548, LPARAMHI = 49151, RESULTLO = 27682, RESULTHI = 16416}, this=0x403d8bd8) at buttons.inc:198 #5 0x0805bbf7 in SYSTEM_TOBJECT_$__DISPATCH$formal () #6 0x080ec6e0 in TCONTROL__WNDPROC (THEMESSAGE={MSG = 1031, WPARAM = 136821192, LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, WPARAMHI = 2087, LPARAMLO = 59548, PARAMHI = 49151, RESULTLO = 27682, RESULTHI = 16416}, this=0x403d8bd8) at control.inc:1447 #7 0x080e4ed9 in TWINCONTROL__WNDPROC (MESSAGE={MSG = 1031, WPARAM = 136821192, LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, WPARAMHI = 2087, LPARAMLO = 59548, PARAMHI = 49151, RESULTLO = 27682, RESULTHI = 16416}, this=0x403d8bd8) at wincontrol.inc:2154 #8 0x08161955 in DELIVERMESSAGE (TARGET=0x403d8bd8, AMESSAGE=void) at gtkproc.inc:3242 #9 0x0818897c in GTKWSBUTTON_CLICKED (AWIDGET=0x8285380, AINFO=0x40453794) at gtkwsbuttons.pp:112 ... { Abgeschnitten zur Vereinfachung} Das komplette Listing ist hier (gdb) _
Beachten sie: Wenn die Ablaufverfolgung zu lang ist werden sie aufgefordert Enter zu drücken, um die nächste Seite anzuzeigen bis die Ablaufverfolgung komplett ist
Die Information, die hier angezeigt wird, hat die Reihenfolge der Ereignisse bis zur Stelle, wo der Fehler aufgetreten ist. Verstehen einer Ablaufverfolgung
Um GDB (und ihr Programm) zu beenden können sie jetzt tippen:
quit {Enter drücken}
Oder um den Ablauf bis zur nächsten Ausnahmebedingung fortzusetzen:
cont {Enter drücken}
Hinweis: Zu jeder Zeit während ihr Programm läuft können sie Ctrl+C drücken (vom Terminal oder MS-DOS Eingabeaufforderung), um eine "(gdb) _" Eingabeaufforderung zu erhalten
Anmerkung: Am besten lässt sich GDB unter Windows mit einem englischen Tastaturlayout verwenden. Ist man auf Sonderzeichen wie ' \ ' angewiesen, kann es Probleme mit dem deutschen Tastaturlayout geben. Im Zweifelsfall sollte man das Layout temporär umstellen.
Wie man die Ablaufverfolgung aus dem Terminal heraus und in eine Email hinein bekommt
Gegenwärtig haben wir eine Ablaufverfolgung erstellt und sie im Terminal(oder MS-DOS Eingabeaufforderung) gesehen aber wie bekomme ich es in eine Email? Es gibt zwei Wege die ich kenne:
- Benutzen sie die Kopieren/Einfügen Funktionalität ihres Terminal(oder MS-DOS Eingabeaufforderung)
- Leiten sie den Output von GDB in eine Datei um etwa so:
gdb project1 > output.txt
Jetzt können sie die Datei öffnen und in ihre Email kopieren/einfügen.
Warnung: Die zweite Methode erfordert, dass sie blind tippen. Daher würden sie "run" tippen um das Programm zu starten und "backtrace" um die Ablaufverfolgung zu erstellen wie normal, aber nichts würde am Bildschirm gezeigt.
Ausnahme: Unter Linux können sie darum herumkommen mit dem folgenden Kommando:
touch output.txt & tail output.txt -f & gdb project1 > output.txt
Verstehen einer Ablaufverfolgung
TODO: Schreiben sie mir :)
(gdb) bt #0 0x080733aa in TFORM1__BUTTON1CLICK (SENDER=0x403d8bd8, this=0x403d77d8) at unit1.pas:36 #1 0x080ecd78 in TCONTROL__CLICK (this=0x403d8bd8) at control.inc:1768 #2 0x081274bd in TBUTTONCONTROL__CLICK (this=0x403d8bd8) at buttoncontrol.inc:57 #3 0x08129171 in TCUSTOMBUTTON__CLICK (this=0x403d8bd8) at buttons.inc:186 #4 0x08129198 in TCUSTOMBUTTON__WMDEFAULTCLICKED (MESSAGE={MSG = 1031, WPARAM = 136821192, LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, WPARAMHI = 2087, LPARAMLO = 59548, LPARAMHI = 49151, RESULTLO = 27682, RESULTHI = 16416}, this=0x403d8bd8) at buttons.inc:198 #5 0x0805bbf7 in SYSTEM_TOBJECT_$__DISPATCH$formal () #6 0x080ec6e0 in TCONTROL__WNDPROC (THEMESSAGE={MSG = 1031, WPARAM = 136821192, LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, WPARAMHI = 2087, LPARAMLO = 59548, LPARAMHI = 49151, RESULTLO = 27682, RESULTHI = 16416}, this=0x403d8bd8) at control.inc:1447 #7 0x080e4ed9 in TWINCONTROL__WNDPROC (MESSAGE={MSG = 1031, WPARAM = 136821192, LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, WPARAMHI = 2087, LPARAMLO = 59548, LPARAMHI = 49151, RESULTLO = 27682, RESULTHI = 16416}, this=0x403d8bd8) at wincontrol.inc:2154 #8 0x08161955 in DELIVERMESSAGE (TARGET=0x403d8bd8, AMESSAGE=void) at gtkproc.inc:3242 #9 0x0818897c in GTKWSBUTTON_CLICKED (AWIDGET=0x8285380, AINFO=0x40453794) at gtkwsbuttons.pp:112 #10 0x401d7877 in gtk_marshal_NONE__NONE () from /usr/lib/libgtk-1.2.so.0 #11 0x40206e5a in gtk_signal_remove_emission_hook () from /usr/lib/libgtk-1.2.so.0 #12 0x4020616a in gtk_signal_set_funcs () from /usr/lib/libgtk-1.2.so.0 #13 0x40204234 in gtk_signal_emit () from /usr/lib/libgtk-1.2.so.0 #14 0x40176e1c in gtk_button_clicked () from /usr/lib/libgtk-1.2.so.0 #15 0x4017838a in gtk_button_get_relief () from /usr/lib/libgtk-1.2.so.0 #16 0x401d7877 in gtk_marshal_NONE__NONE () from /usr/lib/libgtk-1.2.so.0 #17 0x4020607b in gtk_signal_set_funcs () from /usr/lib/libgtk-1.2.so.0 #18 0x40204234 in gtk_signal_emit () from /usr/lib/libgtk-1.2.so.0 #19 0x40176d60 in gtk_button_released () from /usr/lib/libgtk-1.2.so.0 #20 0x40177d26 in gtk_button_get_relief () from /usr/lib/libgtk-1.2.so.0 #21 0x401d764d in gtk_marshal_BOOL__POINTER () from /usr/lib/libgtk-1.2.so.0 #22 0x4020619f in gtk_signal_set_funcs () from /usr/lib/libgtk-1.2.so.0 #23 0x40204234 in gtk_signal_emit () from /usr/lib/libgtk-1.2.so.0 #24 0x40239fd9 in gtk_widget_event () from /usr/lib/libgtk-1.2.so.0 #25 0x401d74d0 in gtk_propagate_event () from /usr/lib/libgtk-1.2.so.0 #26 0x401d65c1 in gtk_main_do_event () from /usr/lib/libgtk-1.2.so.0 #27 0x40065b44 in gdk_wm_protocols_filter () from /usr/lib/libgdk-1.2.so.0 #28 0x4003de75 in g_get_current_time () from /usr/lib/libglib-1.2.so.0 #29 0x4003e32c in g_get_current_time () from /usr/lib/libglib-1.2.so.0 #30 0x4003e4f5 in g_main_iteration () from /usr/lib/libglib-1.2.so.0 #31 0x401d6388 in gtk_main_iteration_do () from /usr/lib/libgtk-1.2.so.0 #32 0x080b4d26 in TGTKWIDGETSET__WAITMESSAGE (this=0x40473014) at gtkobject.inc:1427 #33 0x08070073 in TAPPLICATION__IDLE (this=0x4045b014) at application.inc:319 #34 0x08070ffb in TAPPLICATION__HANDLEMESSAGE (this=0x4045b014) at application.inc:827 #35 0x08071380 in RUNMESSAGE (parentfp=0xbffff5a4) at application.inc:933 #36 0x080712d7 in TAPPLICATION__RUN (this=0x4045b014) at application.inc:944 #37 0x080531c3 in main () at project1.lpr:13 (gdb)
Diese Ablaufverfolgung wurde produziert unter Verwendung dieses Codes:
30. procedure TForm1.Button1Click(Sender: TObject); 31. var 32. X, Y, Z: Integer; 33. begin 34. X := 0; 35. Y := 0; 36. Z := X div Y; 37. end;