使用gdb获得堆栈跟踪信息

好吧,我承认即使知道了进程ID和strace输出结果,但帮助仍然不大,不用急,我还使出绝招呢,绝招就是使用gdb获得堆栈跟踪信息,堆栈跟踪不仅会告诉你程序当前正在做什么,有底层的信息如等待网络套接字),也有较高级别的信息如正在执行什么类型的网络操作)。

和strace的使用方法一样,gdb也使用-p加进程id的命令格式,启动后你会获得一个gdb提示符,输入where就可以获得一个堆栈跟踪。下面是Firefox在运行一些有问题的JavaScript代码时的堆栈跟踪信息。

#0  0x01ad9794 in gfxPangoFontGroup::GetFontAt (this=0xa74e8160, i=0)
    at gfxPangoFonts.cpp:1936
#1  0x01ad1c11 in GetFontOrGroup (this=0xa51466b4, aKey=0xbfab1e2c)
    at gfxTextRunWordCache.cpp:899
#2  TextRunWordCache::CacheHashEntry::KeyEquals (this=0xa51466b4,
    aKey=0xbfab1e2c) at gfxTextRunWordCache.cpp:910
#3  0x01a5cb74 in SearchTable (table=0xb45ce2d0, key=,
    keyHash=, op=PL_DHASH_ADD) at pldhash.c:472
#4  0x01a5cc50 in PL_DHashTableOperate (table=0xb45ce2d0, key=0xbfab1e2c,
    op=) at pldhash.c:661
#5  0x01ad2421 in nsTHashtable::PutEntry (
    this=0xb45ce2c0, aTextRun=0xa7ee0ae0, aFirstFont=0xad613d30, aStart=8,
    aEnd=10, aHash=821, aDeferredWords=0x0)
    at ../../../dist/include/nsTHashtable.h:188
#6  TextRunWordCache::LookupWord (this=0xb45ce2c0, aTextRun=0xa7ee0ae0,
    aFirstFont=0xad613d30, aStart=8, aEnd=10, aHash=821, aDeferredWords=0x0)
    at gfxTextRunWordCache.cpp:358
... etc.

即使你不熟悉Firefox源代码也能从上面的堆栈跟踪结果看出,它正在处理一些和字体有关的事情。

如果程序正在循环,那么它可能一直在做相同的事情,当你运行gdb –p时,它会暂时停止程序以便你进行检查,在提示符后按下c就可以让它继续运行,按下Ctrl-C会再次停止,再输入一次where就会获得第二个堆栈输出。

(gdb) where
#0  0xb686db07 in ?? () from /usr/lib/firefox-3.6.12/libmozjs.so
#1  0xb684bec9 in ?? () from /usr/lib/firefox-3.6.12/libmozjs.so
#2  0xb685cf66 in js_Invoke () from /usr/lib/firefox-3.6.12/libmozjs.so
#3  0xb6b6231b in ?? () from /usr/lib/firefox-3.6.12/libxul.so

这一次结果不一样了,它只暗示Firefox正在处理JavaScriptJS)和XUL相关的事情,反复停止又启动程序,你就会发现它在处理什么事情上花费的时间最多,这些有用的信息可以一并附在你要提交的BUG中,或在搜索引擎中使用其中一些作为关键字进行搜索,看看是否有现成的解决方案。

堆栈跟踪应用到等待资源而挂起的程序上也很好使,下面是我前面使用的Python程序的跟踪结果。

(gdb) where
#0  0x006a2422 in __kernel_vsyscall ()
#1  0x0095d241 in recv () at ../sysdeps/unix/sysv/linux/i386/socket.S:61
#2  0x081301ba in ?? ()
#3  0x081303b4 in ?? ()
#4  0x080e0a21 in PyEval_EvalFrameEx ()
#5  0x080e2807 in PyEval_EvalCodeEx ()
#6  0x080e0c8b in PyEval_EvalFrameEx ()
... etc.

Gdb显示了strace做的一些事情:recv,接下来的内容只告诉你你正在运行Python,但没有告诉你身在Python脚本何处,想知道怎么发掘更多的信息吗?请继续关注下一期文章吧,我将介绍调式Python程序的一些技术,以及在出问题的机器上没有安装gdb等花俏的开发工具时该怎么做。

51CTO.com译稿,转载请注明原文作译者和出处。】

原文:http://www.linuxplanet.com/linuxplanet/tutorials/7232/1/


相关内容