Archive:Development/Tutorials/Debugging/How to create useful crash reports (zh CN)

From KDE TechBase
Revision as of 02:00, 20 December 2009 by Alisha (talk | contribs) (Created page with '{{Template:I18n/Language Navigation Bar|Development/Tutorials/Debugging/How to create useful crash reports}} ==简介== 本文说明如何重现有用的 KDE 应用程序当机...')
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)


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

简介

本文说明如何重现有用的 KDE 应用程序当机(crash)的回溯(backtrace)。首先,提供一些基本信息。然后,我们将说明在几个发行版中如何准备您的 KDE 套件,以获得回溯。这对大多数人就已足够。其他部分是关于如何用 GNU 除错器和 Valgrind 建立回溯,这在某些情况下非常有用。

如何建立有用的当机回报

一份良好的 Bugzilla 当机回报由两部分组成:如何重现当机的描述和当机的回溯。如果缺少其中一个要素,开发人员会很难(但不是不可能)解决问题。

说明不要只有「它当掉了」(it crashed)。尝试描述当机之前的一切情况。按下一个按钮、打开一个特定的网站或档案,才发生问题?这些小细节可能看起来没有什么用,但对开发者来说可能是有用的,所以请把它写下来。

A more insightful article on how to write good bug descriptions is available at this link, please read that before reporting bugs.

不要把回溯放在错误(bug)回报的附件。相反地,简单地贴上回报。这种方式开发者更容易寻找重复的回报,因为附件不会被搜寻到。

如果您贴上回溯到回报,请确定一定从回溯删除所有

(no debugging symbols found)

,不要只有一行或两行,因为会增加阅读上的困难。

即使是直接贴上回溯优于增加一个附件,但请不要贴上其他东西,如日志(Valgrind、strace或终端输出)或范例数据(邮件、HTML档案等)。这些项目请使用附件。

回溯

回溯是不可缺少的。他们对你来说可能看起来毫无意义,但实际上它们含有丰富的有用信息。回溯说明当机之前呼叫哪些函式,使开发者可以追踪哪个函式开始出问题。拥有良好的回溯有一个缺点:函式库和可执行文件占用更多的硬盘空间比其优化的部分。这就是为什么许多发行版选择安装时拿掉档案,结果造成无用的回溯

(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 ?? ()

但不用担心,经过一些修改,您可以建立完整成熟的 KDE 应用程序回溯。

准备你的KDE套件

如果你的发行版有除错功能的套件,请安装它们。

查看回溯很容易发现你缺少哪些除错套件。例如,下一行就是来自回溯:

#6  0xb7975bdc in ?? () from /usr/lib/libkmailprivate.so.4

?? 表示 libkmailprivate.so.4 函式库没有除错信息,它可能是放在单独的除错套件。在这种情况下很容易猜测,您需要安装 KMail 的除错套件以得到更好的回溯。

有时候,你需要安装一个以上的除错套件,才能获得良好的回溯。这取决于发行版如何划分套件。例如说,一些发行版安装 kdepim 除错套件,就可以得到足够的 KMail 当机的除错信息,其他发行版可能还要额外的 KMail 除错套件。

这里有一份发行版如何获得除错套件的列表:

  • Debian - Debian 提供的 -dbg 套件可以更容易建立有用回溯。只要安装对应的 -dbg 套件。例如 kdepim-dbg 用于 KMail 当机。-dbg 的相依性可以确保加入其他正确的套件(kdelibs-dbg、gdb,等)。
  • FreeBSD ports - 请参阅 KDE on FreeBSD FAQ
  • Gentoo - Gentoo 有自己的文件,说明如何进行。
  • Mandriva - Mandriva 2007.0 和之后的版本,KDE 全部都有额外的除错套件(实际上,所有的套件都有)。只要安装对应的 -debug 套件,像 kdebase-debugkdemultimedia-debug 。不管怎样,你可能想安装 kdelibs-debug
    • 注:-debug套件在不同的仓库。例如,在 main 中所有的套件 ,你会发现除错套件在 debug_main 仓库。
  • Kubuntu/Ubuntu - The Ubuntu family makes things quite easy. Every official KDE module has an additional package in the repository, suffixed with -dbg. Always install kdelibs5-dbg, because all KDE applications use kdelibs (kdelibs-dbg for KDE 3 applications). Then you should install a -dbg package for the application which crashed. For example if KOrganizer crashed you should install kdepim-dbg as well. If the program is not from an official KDE module and has no -dbg package, you can install the -dbgsym package from the repository listed on this Debugging Program Crashes page.
    During the Ubuntu development cycle the Apport crash handler is turned on which will report crashes to launchpad.net and do the backtrace for you, if you would rather use the KDE crash handler turn Apport off in /etc/defaults/apport
    Starting with Lucid Lynx (10.04) Kubuntu will be forwarding all non kubuntu specific bugs upstream and had disabled Apport so that DrKonqui will be th edefault crash handler.
  • openSUSE - 你只需要安装 -debuginfo 套件,例如:kdepimlibs4-debuginfo。您可以在KDE 套件库找到这些套件。此外还有一个专门的openSUSE 除错页面
  • Fedora - Fedora 有自己的文件,说明如何进行。(必须启用 debuginfo 套件库。)

如果你的发行版没有除错功能的 KDE 套件,你必须从原始码编译 KDE:

  • 如果你使用 KDE 4,在 CMake 阶段,你应该使用 -DCMAKE_BUILD_TYPE=debugfull 参数。如果你想指定自己的 CXXFLAGS,请使用-DCMAKE_BUILD_TYPE=None CMAKE_CXX_FLAGS="-O0 -g" 。您可以根据您的需要更改 CMAKE_CXX_FLAGS。

接者只是 makemake install,就像你所熟悉的。

当机!

当你的应用程序当机的时候。KDE 当机对话框应该会在当机后出现,它会显示回溯分页。

KDE 当机对话框
KDE 当机对话框

单击该分页,并稍等一下。过程可能需要相当内存,因此可能会突然变慢。但结束后应该会改善。例如:

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

这样看起来好多了,对不对?它显示内存地址、原始码档案和行号和传递给函式的参数。这样更有助于开发人员找到问题。

Template:Note (zh CN)

使用 GDB 检索回溯

在某些情况下,不可能建立一个 KDE 当机对话框的回溯。这可能是由于应用程序,进入了无限循环,或当机对话框因为某种原因并没有出现。您可以尝试使用gdbGNU Debugger)取得回溯。GDB is widely available through distribution packages.

可以在不同的情况呼叫 GDB 。您可以从 gdb 内部执行应用程序,或附加 gdb 到一个已执行的行程。后者当应用程序,已经进入了无限循环时,可能是有用的。但是,我们先由在 gdb 内部执行应用程序开始。在 shell,执行:

$ gdb someKDEapp

GDB 将出现提示。请注意,这不会启动应用程序本身,你应该透过呼叫 run 指令执行它:

(gdb) run

这将执行应用程序,就像你习惯的一样,你可以像平常一样使用它(它仅消耗更多的内存,并可能觉得缓慢)。现在是时候重现你的当机。当你成功时,应用程序只会关闭,然后您应该回到 GDB 提示。现在是时候执行「backtrace」指令:

Template:Note (zh CN)

(gdb) thread apply all backtrace

应该会出现一个可张贴在 KDE Bugzilla 的良好回溯。

如果要附加到现有的行程中,请在 shell 执行以下指令:

$ gdb someKDEapp pid

where pid is the process ID of the process you want to attach to. Once attached, and the process is in an infinite loop, after using the 'backtrace' command again a useful backtrace will appear. You can use 'continue' command to let the application run again and press Ctrl+C in gdb to be able to again enter commands.

使用 Valgrind 检索回溯

When it comes to crashes, Valgrind is also a useful tool to create a backtrace. It's not a substitution for GDB, but rather a supplement.

When you run an application in valgrind, every piece of memory read or written by the application is being checked. Valgrind will report erroneous memory operations in the standard output or in a log file. Since most crashes are due to an invalid memory read, valgrind can be useful to track down where the problem occurs.

Template:Note (zh CN)

Like GDB, Valgrind makes running an application much slower, while consuming a lot more resources.

Start the application within valgrind:

$ valgrind --log-file=someKDEapp someKDEapp

Now reproduce the crash. As soon as this happens, the application and valgrind will terminate. What's left is a file named someKDEapp.pid where pid is replaced by the process ID of the valgrind process. The file may list more errors than the one causing the crash. Here's the bit causing the crash which corresponds to the GDB backtrace above:

==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

But to be sure, just attach the whole log file to the crash report.