Table of Contents

调试 Xfce

当然,我们都知道 Xfce 是 bugfree and stable as a rock。所以这份 HOWTO 没啥存在的理由。

可是,一些(yet)未知的原因,会引起应用程序崩溃。我们不确定这些神奇事件的源头。有些人亲眼目睹 Rodents 的存在,这中间可能有些联系,但不确切。

不管怎样,如果有神秘事件发生,这一种可以帮助开发都解决问题的手段:

确认崩溃

当应用程序崩溃时,它通常会由于 SIG_SEGV 信号,或段错误退出。这意味着该操作系统检测到应用程序试图访问不允许访问的内存块(段)。操作系统向应用程序发送信号,从而引起应用程序立即中止。

如果应用程序从终端启动,输出可能像下面这样:

stephan@hermes:~$ ristretto
段错误
stephan@hermes:~$

这条消息只是简短的描述,让我们尝试找出它崩溃的原因。

在调试器中运行程序

要找出应用程序为什么崩溃,首先要在调试器中运行它。 GNU/Linux 上最常用的调试器是 gdb(GNU 调试器)。

使用 gdb ,你只用从命令行里启动它,把要调试应用程序作为它第一个参数,看下面的例子:

stephan@hermes:~$ gdb ristretto 
GNU gdb (GDB) 7.3-debian
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /usr/local/bin/ristretto...done.
(gdb) 

现在 gdb 是启动了,但应用程序还没有做任何事情。 要启动的应用程序,键入run,一些你可能想给应用程序的参数,然后按Enter

现在,如果应用程序没有立即崩溃,你可以看到它启动了并且调试器里出现几行字。(见下面的例子)

...
(gdb) run
Starting program: /usr/local/bin/ristretto 
[Thread debugging using libthread_db enabled]

现在,执行让应用程序崩溃所需的动作。下一步的调试器看起来像这样:

(gdb) run
Starting program: /usr/local/bin/ristretto 
[Thread debugging using libthread_db enabled]
[New Thread 0x7fffe5780700 (LWP 26386)]

Program received signal SIGSEGV, Segmentation fault.
0x00000000004206f9 in rstto_monitor_chooser_paint (widget=0x6f1d60)
    at monitor_chooser.c:300
warning: Source file is more recent than executable.
300	                if (monitor->width > monitor->height)
(gdb) 

当然,应用程序的不同,或 bug 的不同会有不同的输出,所以如果输出不一样不用担心。

下一步是得到一个所谓的“回溯”(backtrace)。回溯可以追踪到导致应用程序崩溃的流程:

(gdb) backtrace
#0  0x00000000004206f9 in rstto_monitor_chooser_paint (widget=0x6f1d60)
    at monitor_chooser.c:300
#1  0x00000000004204b2 in rstto_monitor_chooser_expose (widget=0x6f1d60, 
    event=0x7fffffffc9b0) at monitor_chooser.c:235
#2  0x00007ffff78dc418 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#3  0x00007ffff5d1f03e in g_closure_invoke () from /usr/lib/libgobject-2.0.so.0
#4  0x00007ffff5d2fced in ?? () from /usr/lib/libgobject-2.0.so.0
#5  0x00007ffff5d3944b in g_signal_emit_valist ()
   from /usr/lib/libgobject-2.0.so.0
#6  0x00007ffff5d39832 in g_signal_emit () from /usr/lib/libgobject-2.0.so.0
#7  0x00007ffff79f5301 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#8  0x00007ffff78dac30 in gtk_main_do_event ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#9  0x00007ffff752db0c in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0
#10 0x00007ffff752dabb in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0
#11 0x00007ffff7528ad3 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0
#12 0x00007ffff752ac71 in gdk_window_process_all_updates ()
   from /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0
#13 0x00007ffff785e301 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#14 0x00007ffff7508286 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0
#15 0x00007ffff5454edd in g_main_context_dispatch () from /lib/libglib-2.0.so.0
#16 0x00007ffff54556b8 in ?? () from /lib/libglib-2.0.so.0
#17 0x00007ffff5455cfa in g_main_loop_run () from /lib/libglib-2.0.so.0
#18 0x00007ffff786154b in gtk_dialog_run ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#19 0x0000000000421da6 in rstto_xfce_wallpaper_manager_configure_dialog_run (
    self=0x6cb620, file=0xa68b00) at xfce_wallpaper_manager.c:154
#20 0x000000000041ff76 in rstto_wallpaper_manager_configure_dialog_run (
    self=0x6cb620, file=0xa68b00) at wallpaper_manager.c:38
#21 0x000000000041d689 in cb_rstto_main_window_set_as_wallpaper (
    widget=0x80c810, window=0x66d360) at main_window.c:1890
#22 0x00007ffff5d1f03e in g_closure_invoke () from /usr/lib/libgobject-2.0.so.0
#23 0x00007ffff5d2fedb in ?? () from /usr/lib/libgobject-2.0.so.0
#24 0x00007ffff5d3968a in g_signal_emit_valist ()
   from /usr/lib/libgobject-2.0.so.0
#25 0x00007ffff5d39832 in g_signal_emit () from /usr/lib/libgobject-2.0.so.0
#26 0x00007ffff781a683 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#27 0x00007ffff5d1f03e in g_closure_invoke () from /usr/lib/libgobject-2.0.so.0
#28 0x00007ffff5d2f665 in ?? () from /usr/lib/libgobject-2.0.so.0
#29 0x00007ffff5d3968a in g_signal_emit_valist ()
   from /usr/lib/libgobject-2.0.so.0
#30 0x00007ffff5d39832 in g_signal_emit () from /usr/lib/libgobject-2.0.so.0
#31 0x00007ffff79f44fe in gtk_widget_activate ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#32 0x00007ffff78ef87d in gtk_menu_shell_activate_item ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#33 0x00007ffff5d1f03e in g_closure_invoke () from /usr/lib/libgobject-2.0.so.0
#34 0x00007ffff5d2fced in ?? () from /usr/lib/libgobject-2.0.so.0
#35 0x00007ffff5d38c60 in g_signal_emitv () from /usr/lib/libgobject-2.0.so.0
#36 0x00007ffff7827d5a in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#37 0x00007ffff78282b8 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#38 0x00007ffff7828512 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#39 0x00007ffff782946a in gtk_bindings_activate_event ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#40 0x00007ffff78ee928 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#41 0x00007ffff78e54c2 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#42 0x00007ffff78dc418 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#43 0x00007ffff5d1f03e in g_closure_invoke () from /usr/lib/libgobject-2.0.so.0
#44 0x00007ffff5d2fced in ?? () from /usr/lib/libgobject-2.0.so.0
#45 0x00007ffff5d3944b in g_signal_emit_valist ()
   from /usr/lib/libgobject-2.0.so.0
#46 0x00007ffff5d39832 in g_signal_emit () from /usr/lib/libgobject-2.0.so.0
#47 0x00007ffff79f5301 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#48 0x00007ffff78da686 in gtk_propagate_event ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#49 0x00007ffff78da933 in gtk_main_do_event ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#50 0x00007ffff754621c in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0
#51 0x00007ffff5454edd in g_main_context_dispatch () from /lib/libglib-2.0.so.0
#52 0x00007ffff54556b8 in ?? () from /lib/libglib-2.0.so.0
#53 0x00007ffff5455cfa in g_main_loop_run () from /lib/libglib-2.0.so.0
#54 0x00007ffff78d9987 in gtk_main ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#55 0x000000000042a36d in main (argc=1, argv=0x7fffffffe428) at main.c:157
(gdb)

将它复制到一个文本文件中,并把它添加到 https://bugzilla.xfce.org/ 的 bug 报告。

但如果回溯的最后一行以 0x000000000000(空指针)开始, then the backtrace is not of any good。应用程序跳转到一个空指针,然后在内存里瞎跑一阵最后死掉。如果是这种情况,请尝试使用 valgrind 。 –(未完待续)