Development/Tutorials/Debugging/How to create useful crash reports (de): Difference between revisions

From KDE TechBase
(Restore original version)
m (Correct language template)
Line 1: Line 1:
{{Template:I18n/Language Navigation Bar|Entwicklung/Tutorials/Debugging/Wie man einen vernünftigen Bugreport erstellt}}
{{Template:I18n/Language Navigation Bar|Development/Tutorials/Debugging/How to create useful crash reports}}
==Einleitung==
==Einleitung==



Revision as of 09:05, 30 August 2010


Development/Tutorials/Debugging/How to create useful crash reports

Einleitung

Dieses Dokument beschreibt, wie man einen Backtrace eines abgestürzten KDE-Programmes reproduziert. Zunächst ein wenig generelle Informationen. Danach wird beschrieben, wie man für verschiedene Distributionen die KDE-Pakete vorbereitet und man einen Backtrace bekommen kann. Dies sollte genug für die meisten Leute sein. Es existieren weitere Abschnitte über das Erstellen von Backtraces mit dem GNU Debugger und mit Valgrind, die in manchen Fällen hilfreich sind.

Wie man einen vernünftigen Bugreport erstellt

Ein guter Bugreport auf [1] besteht aus zwei Teilen: Einer Beschreibung, die angibt, wie man den Absturz reproduziert und einem Backtrace des Absturzes. Wenn eines dieser beiden Elemente fehlt, ist es viel schwerer (wenn nicht sogar unmöglich) für Entwickler, das Problem anzugehen.

Eine Beschreibung sollte aus mehr bestehen als nur "it crashed". Es sollte versucht werden, alles zu beschreiben, das der Benutzer tat, befor der Absturz geschah. Wurde auf einen Button geklickt, wurde eine spezielle Webseite geöffnet oder war es eine spezielle Datei, die Probleme verursachte? Diese kleinen Details, die vielleicht unbrauchbar erscheinen, können den Entwicklern hilfreich sein, deshalb sollten sie erwähnt werden.

Ein aufschlussreicherer Artikel über das Schreiben von guten Bugbeschreibungen ist unter der Adresse [http://www.chiark.greenend.org.uk/~sgtatham/bugs.html zu finden. Es ist erbeten, den Artikel zu lesen, bevor ein Bug gemeldet wird.

Bitte den Backtrace nicht dem Bugreport anhängen, sondern ihn einfach in den Bugreport einfügen. Auf diese Weise ist es für die Entwickler viel einfach, duplizierte Bugreporte zu finden, weil Anhänge nicht durchsucht werden.

Wenn ein Backtrace gemeldet wird, sollten alle bis auf ein oder zwei dieser Zeilen aus dem Backtrace entfernt werden, weil sie ihn schwerer lesbar machen:

(no debugging symbols found)

Obwohl das direkte Kopieren von Backtraces über das Anhängen als Anhang bevorzugt wird, ist das direkte Kopieren von Logs (Valgrind, Strace oder Terminalausgabe) oder Beispieldaten (mails, HTML-Dateien und so weiter)nicht erwünscht.Für diese Dateiformen ist die Anhangfunktion gedacht.

Backtraces

Backtraces sind essentiell. Für den normalen Benutzer mögen sie nutzlos aussehen, aber möglicherweise enthalten sie unzählige nutzbare Informationen. Ein Backtrace beschreibt, welche Funktionen vor dem Absturz aufgeruschen wurden, sodass Entwickler die Funktion aufspüren können, in der der Absturz begann. Gute Bugtraces zu haben hat einen Nachteil: Libraries und ausführbare Dateien nehmen viel mehr Platz ein, als ihre optimierten Kopien. Das ist der Grund, warum viele Distributionen schlankere Dateien installieren, die in nutzlosen Backtraces resultieren':

(no debugging symbols found)
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
[Thread debugging using libthread_db enabled]
[New Thread -1233848624 (LWP 12212)]
[New Thread -1255081072 (LWP 12820)]
[New Thread -1240921200 (LWP 12819)]
[New Thread -1266680944 (LWP 12818)]
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
0xffffe410 in __kernel_vsyscall ()
#0  0xffffe410 in __kernel_vsyscall ()
#1  0xb6a1210b in ?? () from /lib/tls/i686/cmov/libpthread.so.0
#2  0xb6a85afe in ?? () from /usr/lib/libX11.so.6
#3  0x00000003 in ?? ()
#4  0x082149c0 in ?? ()
#5  0x00003ffc in ?? ()
#6  0x00000000 in ?? ()

Aber keine Sorgen, mit einigen Modifikationen können nützliche und komplette Bugtraces für KDE-Applikationen erstellt werden.

Die KDE-Pakete vorbereiten

Wenn die Distribution Pakete hat, die das Debugging aktiviert, solllten sie installiert werden. Hier ist eine Liste von How-Tos für einige Distributionen:

  • Debian - Debian bietet -dbg-Pakete, um einach nützliche Backtraces zu erstellen. Es müssen einfach die entsprechenden -dbg-Pakete installiert werden. Beispielsweise kdepim-dbg Für Abstürze von kmail. Die Abhängigkeiten von -dbg sorgen dafür, dass die anderen benötigten Pakete (kdelibs-dbg, gdb und so weiter) installiert werden.
  • FreeBSD-Portierungen - Bitte an den KDE unter FreeBSD-Guide wenden.
  • Gentoo - Gentoo hat sein eigenes Dokument, das beschreibt, wie vorgegangen werden soll.
  • Mandriva - Mandriva 2007.0 und darüber hat ein weiteres Debuggingpaket für KDE (eigentlich für all seine Pakete). Es muss nur das entsprechende -debug-Paket installiert werden, wie kdebase-debug und kdemultimedia-debug. Es sollte auch kdelibs-debug installiert werden.
    • Notiz: Die -debug-Pakete sind in separaten Repositories. Zum Beispiel sind alle Pakete in main im Repository debug_main zu finden.
  • Kubuntu/Ubuntu - Die Ubungufamilie macht Debugging sehr einfach. Jedes offizielle KDE-Modul hat ein zusätzliches Paket mit dem Suffix -dbg im Repository. Es muss immer kdelibs-dbg installiert werden, weil alle KDE-Programme kdelibs benutzen. Danach sollte ein -dbg-Paket für das abgestürzte Programm installiert werden. Zum Beispiel kdepim-dbg, wenn KOrganizer abgestürzt ist.
  • openSUSE - openSUSE bietet ein separates Repository für den Download von Debug-Pakete. Unter der Adresse[2] ist die aktuelle URL zu finden. Es existiert auch eine dedizierte openSUSE-Debuggingseite.
  • Fedora - Fedora hat sein eigenes Dokument, das beschreibt, wie vorgegangen werden soll. (Ein Debuggingrepository muss aktiviert werden.)

Wenn die Distribution keine Pakete hat, die das Debugging einschalten, muss KDE aus dem Quelltext kompiliert werden:

  • Wenn KDE 3 benutzt wird, muss im Konfigurationsschritt der Parameter --enable-debug=full angegeben werden, damit der Debugmodus in den entstehenden Dateien eingeschaltet wird.
  • Wenn KDE 4 benutzt wird, muss im cmake-Schritt der Parameter -DCMAKE_BUILD_TYPE=debugfull angegeben werden. Wenn seigene CXXFlags angegeben werden sollen, sollte der Parameter -DCMAKE_BUILD_TYPE=None CMAKE_CXX_FLAGS="-O0 -g" verwendet werden. Die CMAKE_CXX_FLAGS können entsprechen angepasst werden.

Danach nur noch make und make install, wie bekannt.

Absturz!

Nun ist es an der Zeit, das Programm zu crashen. Der KDE-Absturz-Dialog sollte direkt nach dem Absturz erscheinen, der das Backtrace-Tab anzeigt.

KDE-Crash-Dialog
KDE-Crash-Dialog

Der Prozess, der erscheint, nachdem man auf den Tag geklickt hat, mag durchaus viel Speicher belegen, sodass das System auf einmal träge werden kann. Aber das Ergebnis sollte viel besser aussehen. Zum Beispiel:

Using host libthread_db library "/lib/libthread_db.so.1". 
[Thread debugging using libthread_db enabled] 
[New Thread -1232783168 (LWP 7604)] 
[KCrash handler] 
#6  0x0806be76 in TreeMapItem::parent (this=0x0) 
    at /home/bram/KDE/kde3/kdeaddons/konq-plugins/fsview/treemap.h:285 
#7  0x08065fea in TreeMapItemList::compareItems (this=0xbfec04a8, item1=0x0, 
    item2=0x0) 
    at /home/bram/KDE/kde3/kdeaddons/konq-plugins/fsview/treemap.cpp:720 
#8  0xb7281619 in QGList::operator== () from /usr/qt/3/lib/libqt-mt.so.3 
#9  0x0806d498 in QPtrList<TreeMapItem>::operator== (this=0xbfec04a8, 
    list=@0xbfec0468) at /usr/qt/3/include/qptrlist.h:74 
#10 0x08062e18 in TreeMapWidget::mousePressEvent (this=0xbfec03ac, 
    e=0xbfebff1c) 
    at /home/bram/KDE/kde3/kdeaddons/konq-plugins/fsview/treemap.cpp:1840 
#11 0xb7004a63 in QWidget::event () from /usr/qt/3/lib/libqt-mt.so.3 
#12 0xb6f6bca7 in QApplication::internalNotify () 
   from /usr/qt/3/lib/libqt-mt.so.3 
#13 0xb6f6ca88 in QApplication::notify () from /usr/qt/3/lib/libqt-mt.so.3 
#14 0xb7725a84 in KApplication::notify (this=0xbfec055c, receiver=0xbfec03ac, 
    event=0xbfebff1c) 
    at /home/bram/KDE/kde3/kdelibs/kdecore/kapplication.cpp:550 
#15 0xb6f0bfd2 in QETWidget::translateMouseEvent () 
   from /usr/qt/3/lib/libqt-mt.so.3 
#16 0xb6f0b8b0 in QApplication::x11ProcessEvent () 
   from /usr/qt/3/lib/libqt-mt.so.3 
#17 0xb6f1b761 in QEventLoop::processEvents () from /usr/qt/3/lib/libqt-mt.so.3 
#18 0xb6f82831 in QEventLoop::enterLoop () from /usr/qt/3/lib/libqt-mt.so.3 
#19 0xb6f826b6 in QEventLoop::exec () from /usr/qt/3/lib/libqt-mt.so.3 
#20 0xb6f6b72f in QApplication::exec () from /usr/qt/3/lib/libqt-mt.so.3 
#21 0x0805181e in main (argc=134673960, argv=0xffffffff) 
    at /home/bram/KDE/kde3/kdeaddons/konq-plugins/fsview/main.cpp:55

Dies sieht doch schon viel besser aus, oder? Es zeigt Speicheradressen, Quelldateien und Zeilennummern und die Parameter, die an die Funktionen übergeben wurden. Dies macht es viel hilfreicher für die Etwickler, die nun wissen, wo sie nachsehen müssen.

Note
GDB muss' installiert sein, um ein Backtrace zu erhalten. Im nächsten Absatz wird erklärt, was GDB ist und wie man es installiert.


Einen Backtrace mit GDB erhalten

In einigen Fällen ist es nicht möglich, einen Backtrace mit dem KDE-Absturz-Dialog zu erstellen. Dies mag an einer Applikation liegen, die in einer unendlichen Schleife ist, oder der Absturzdialog erschien aus irgendeinem Grund nicht. Mit gdb, dem GNU-Debugger kann ein Backtrace erzeugt werden. GDB ist durch Distributionspakete weit verbreitet.

Der Aufrug von GDB ist in verschiedenen Situationen unterschiedlich. Eine Applikation kann in GDB aufgerufen werden, oder GDB kann an einen bereits laufenden Prozess angehängt werden. Diese Methode ist hilfreich, wenn eine Anwendung bereits in einer unendlichen Schleife ist. Aber zunächst wird gezeigt, wie Applikationen innerhalb von GDB gestartet werden können. Terminalaufruf:

$ gdb IrgendeineKDEApp

Die GDB-Kommandozeile wird erscheinen. Zu beachten ist, dass dieser Aufruf nicht die Applikation selbst aufruft, sie muss durch den Befehltt>run Befehl: aufgerufen werden.

(gdb) run

Dies wird die Applikation wie üblich aufrufen und sie kann normal benutzt werden (Es wird nur viel mehr Speicher benutzt und das Programm kann träge wirken). Jetzt ist es an der Zeit, den Absturz zu reproduzieren. Bei Erfolg schließt die Applikation und kehrt zur GDB-Kommandozeile zurück. Jetzt ist es an der Zeit, den Backtracebefehl auszuführen:

Note
Einige KED-Applikationen (so wie JuK und KTorrent) enthalten speziellen Code, um sicherzustellen, dass nur eine Instanz der Applikation gleichzeitig läuft. Bei diesen Applikationen sollte der Befehl "run --nofork" auf dem GDB-Prompt anstelle "run" verwendet werden, weil GDB sonst versucht, den falschen Prozess zu debuggen. Bei Unsicherheit sollte --nofork ausprobiert werden. Wenn die Applikation sagt, dass --nofork eine unbekannte Option ist, kann es einfach entfernt werden.


(gdb) backtrace

Dies sollte einen guten Bugtrace ergeben, der in der KDE-Bugzilla gepostet werden kann.

Falls GDB an einen existierenden Prozess angehängt werden soll, wird dieser Befehl benutzt:

$ gdb IrgendeineKDEApp pid

pid ist die Prozess-ID des Prozesses, an den GDB angehängt werden soll. Wemm GDB amgehängt ist und der Prozess in eine unendliche Schleife eintritt, erscheint nach der Benutzung des 'backtrace'-Befehls ein nützlcher Bugtrace. Mit dem Befehl 'continue' kann die Applikation fortgesetzt werden und mit Crtl+C in GDB können wieder Befehle eingegeben werden.

Einen Backtrace mit Valgrind erhalten

Was Abstürze angeht, ist Valgrind auch ein nützliches Programm, um einen Backtrace zu erzeugen. Es ist kein Ersatz für GDB, sondern ein Zusatz.

Wenn eine Applikation in Valgrind ausgeführt wird, wird jeder Speicherbereich, der von der Applikation gelesen oder beschrieben wird, getestet. Valgrind meldet fehlerhafte Speicheroperationen in der Standardausgabe oder in einer Logdatei. Weil die meisten Abstürze an ungültigen Speicherzugriffen liegen, kann Valgrind nützlich sein, um zu verfolgen, wo der Fehler geschieht.

Note
Valgrind besteht aus mehreren Teilen, um eine Applikation zu testen. In diesem Artikel wird nur memchek benutzt, das Standardwerkzeug, das benutzt wird, wenn Valgrind aufgerufen wird.


Wie GDB laufen die Applikationen in Valgrind viel langsamer, während sie viel mehr Ressourcen belegen.

Das Starten der Applikation in Valgrind:

$ valgrind --log-file=IrgendeineKDEApp IrgendeineKDEApp

Jetzt muss der Absturz reproduziert werden. Sobald dies geschieht, werden die Applikation und Valgrind beendet. Übrig bleibt eine Datei mit dem Namen IrgendeineKDEApp.pid. pid wird durch die Prozess-ID des Valgrindprozesses ersetzt. Die Datei kann mehr Fehler auflisten, als der Fehler, der den Absturz verursacht hat. Hier ist der Teil, der mit GDB-Backtrace oben übereinstimmt:

==23292== Invalid read of size 4
==23292==    at 0x806BD9E: TreeMapItem::parent() const (treemap.h:285)
==23292==    by 0x8065FB9: TreeMapItemList::compareItems(void*, void*) (treemap.cpp:720)
==23292==    by 0x50AC618: QGList::operator==(QGList const&) const (in /usr/qt/3/lib/libqt-mt.so.3.3.8)
==23292==    by 0x806D3BF: QPtrList<TreeMapItem>::operator==(QPtrList<TreeMapItem> const&) const (qptrlist.h:74)
==23292==    by 0x8062DE7: TreeMapWidget::mousePressEvent(QMouseEvent*) (treemap.cpp:1840)
==23292==    by 0x4E2FA62: QWidget::event(QEvent*) (in /usr/qt/3/lib/libqt-mt.so.3.3.8)
==23292==    by 0x4D96CA6: QApplication::internalNotify(QObject*, QEvent*) (in /usr/qt/3/lib/libqt-mt.so.3.3.8)
==23292==    by 0x4D97A87: QApplication::notify(QObject*, QEvent*) (in /usr/qt/3/lib/libqt-mt.so.3.3.8)
==23292==    by 0x4809AC3: KApplication::notify(QObject*, QEvent*) (kapplication.cpp:550)
==23292==    by 0x4D36FD1: QETWidget::translateMouseEvent(_XEvent const*) (in /usr/qt/3/lib/libqt-mt.so.3.3.8)
==23292==    by 0x4D368AF: QApplication::x11ProcessEvent(_XEvent*) (in /usr/qt/3/lib/libqt-mt.so.3.3.8)
==23292==    by 0x4D46760: QEventLoop::processEvents(unsigned) (in /usr/qt/3/lib/libqt-mt.so.3.3.8)
==23292==  Address 0x2C is not stack'd, malloc'd or (recently) free'd

Um sicher zu sein, sollte die gesammte Datei an den Absturzreport angehängt werden.