Template:I18n/Language Navigation Bar (zh CN)
Contents |
本文说明如何重现有用的 KDE 应用程序当机(crash)的回溯(backtrace)。首先,提供一些基本信息。然后,我们将说明在几个发行版中如何准备您的 KDE 套件,以获得回溯。这对大多数人就已足够。其他部分是关于如何用 GNU Debugger 和 Valgrind 建立回溯,这在某些情况下非常有用。
一份良好的 Bugzilla 当机回报由两部分组成:如何重现当机的描述和当机的回溯。如果缺少其中一个要素,开发人员会很难(但不是不可能)解决问题。
说明不要只有「它当掉了」(it crashed)。尝试描述当机之前的一切情况。按下一个按钮、打开一个特定的网站或档案,才发生问题?这些小细节可能看起来没有什么用,但对开发者来说可能是有用的,所以请把它写下来。
一份更有深刻见解的文章,如何写出好的错误的描述可以在此链接找到,请在回报错误之前阅读它。
不要把回溯放在错误(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 应用程序回溯。
如果你的发行版有除错功能的套件,请安装它们。
查看回溯很容易发现你缺少哪些除错套件。例如,下一行就是来自回溯:
#6 0xb7975bdc in ?? () from /usr/lib/libkmailprivate.so.4
?? 表示 libkmailprivate.so.4 函式库没有除错信息,它可能是放在单独的除错套件。在这种情况下很容易猜测,您需要安装 KMail 的除错套件以得到更好的回溯。
有时候,你需要安装一个以上的除错套件,才能获得良好的回溯。这取决于发行版如何划分套件。例如说,一些发行版安装 kdepim 除错套件,就可以得到足够的 KMail 当机的除错信息,其他发行版可能还要额外的 KMail 除错套件。
这里有一份发行版如何获得除错套件的列表:
如果你的发行版没有除错功能的 KDE 套件,你必须从原始码编译 KDE:
接者只是 make 和 make install,就像你所熟悉的。
当你的应用程序当机的时候。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
这样看起来好多了,对不对?它显示内存地址、原始码档案和行号和传递给函式的参数。这样更有助于开发人员找到问题。
在某些情况下,不可能建立一个 KDE 当机对话框的回溯。这可能是由于应用程序,进入了无限循环,或当机对话框因为某种原因并没有出现。您可以尝试使用gdb(GNU Debugger)取得回溯。GDB is widely available through distribution packages.
可以在不同的情况呼叫 GDB 。您可以从 gdb 内部执行应用程序,或附加 gdb 到一个已执行的行程。后者当应用程序,已经进入了无限循环时,可能是有用的。但是,我们先由在 gdb 内部执行应用程序开始。在 shell,执行:
$ gdb someKDEapp
GDB 将出现提示。请注意,这不会启动应用程序本身,你应该透过呼叫 run 指令执行它:
(gdb) run
这将执行应用程序,就像你习惯的一样,你可以像平常一样使用它(它仅消耗更多的内存,并可能觉得缓慢)。现在是时候重现你的当机。当你成功时,应用程序只会关闭,然后您应该回到 GDB 提示。现在是时候执行「backtrace」指令:
| 一些 KDE 应用程序(如 JuK 和 KTorrent)有特殊的程序代码,确保同时只有一个应用程序实例执行。对于这些应用程序你应该在(gdb)提示输入「run --nofork」,而不是「run」,因为用别的方法 gdb 将尝试除错错误的行程。如果您不确定是否要用 --nofork 可以只试看看。如果应用程序说这是一个未知的选项,您可以删除 --nofork。 |
|---|
| 附注 |
(gdb) thread apply all backtrace
应该会出现一个可张贴在 KDE Bugzilla 的良好回溯。
如果要附加到现有的行程中,请在 shell 执行以下指令:
$ gdb someKDEapp pid
其中pid是你想要附加行程的 ID。一旦附加,而这个行程又是一个无限回圈,在使用「backtrace」指令后将出现一个有用的回溯。你可以使用「continue」指令,让应用程序继续执行,在 gdb 按下 Ctrl+C 能够再次回到命令。
当涉及到当机,Valgrind 也是一个建立回溯的有用工具。这不是一个GDB替代品,而是一个补充。
当您在 Valgrind 执行应用程序时,每一块应用程序读取或写入的内存都会检查。Valgrind 会在标准输出或日志文件中,回报错误的记忆体操作。由于大多数当机是由于无效的内存读取,Valgrind 可用于追踪什么地方发生问题。
和 GDB一样,Valgrind 使得应用程序执行变慢,而且消耗很多资源。
在valgrind 内部启动应用程序:
$ valgrind --log-file=someKDEapp someKDEapp
现在重现当机。这件事一发生,应用程序和 Valgrind 就会终止。只留下一个名为 someKDEapp.pid 的档案,其中 pid 是代表 Valgrind 行程的 ID。这个档案可能会列出比当机原因更多的错误。这里是对应于上面 GDB 回溯的当机原因:
==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
但可以肯定是,只要把整个日志文件放到当机回报的附件。