我可以通过数据转储找出Python应用崩溃的位置吗?

9 投票
5 回答
30005 浏览
提问于 2025-04-15 17:41

我最近在一个客户的电脑上遇到了应用程序崩溃的问题。我怀疑这可能是因为PyQt自己的内存管理不当,导致了无效的内存访问。

当Python这样崩溃时,不会打印出错误追踪信息,只会把一些数据写入磁盘。

有没有可能找出崩溃发生在Python代码的哪个地方呢?

这是数据转储的链接: http://pastie.org/768550

5 个回答

1

不太确定这是否有帮助,但如果你能捕捉到异常的话,可以使用http://github.com/gooli/pydump这个工具来保存一个快照,然后在Python调试器中再加载它。

3

在Python的源代码中,有一个叫做 gdbinit 的文件(在 Misc/gdbinit 目录下),它提供了一些宏命令,可以帮助我们在使用gdb调试时显示当前的解释器状态。你只需要在gdb中输入 source gdbinit,然后就可以使用像 pystack 这样的宏命令了。想要查看可用的宏命令,只需阅读这个文件的源代码就可以了。
(你可以直接在这里找到它: http://svn.python.org/view/python/trunk/Misc/gdbinit?view=log。)

当然,如果程序崩溃得很严重,导致解释器内部结构被破坏,那么这些宏命令可能会失效或者导致程序再次崩溃。此外,最好在调试模式下编译解释器,否则gdb可能找不到需要的符号和变量。

8

这是一个Linux的核心转储文件吗?如果是的话,你可以用gdb来查看它。你需要在一个和出问题的系统完全一样的环境下运行,包括操作系统和Python的版本,还有第三方库。你可以运行 gdb -c /path/to/core/file。当gdb加载完成后,输入 bt 命令可以列出主线程的调用栈,输入 thread apply all bt 可以列出所有线程的调用栈。

这个信息有多有用,取决于你用的Python版本是否包含完整的符号表(也就是说,是否是调试版本的Python)。如果不是的话,你看到的只会是一些地址,指向主要的C语言入口点。不过,这些信息在诊断问题时还是有一定帮助的。

如果你用的是其他不支持gdb的操作系统,那就得自己想办法了——估计那个操作系统会有自己的调试工具。

补充:

在Python的维基上有一篇文章,讲述了 如何用gdb获取Python的调用栈

不过,快速查看问题中的链接显示,操作系统是Windows,所以gdb没什么用。Windows的转储信息比较少,所以我觉得你可能没什么机会了。

我能给出的建议是:

  1. 尝试在内部重现崩溃。

  2. 让用户在运行一个可以捕捉崩溃并进行正确内存转储的工具时重现这个bug。我已经有十年没做过Windows调试了,所以不太清楚现在有哪些工具可用——以前有一个叫Dr.Watson的工具,但可能已经过时了。

如果用户无法重现崩溃,那你就没办法了;但如果之后再也没有发生过,那其实也不是大问题。;-)

更新:

谷歌告诉我,Dr.Watson仍然是Windows XP(以及其他版本的Windows)的默认崩溃处理程序——问题中提到的堆栈转储可能就是来自它。不过,Dr.Watson默认保存的数据比较少,但你可以配置它保存更多的信息——可以参考 这篇文章。简单来说,如果你运行 drwtsn32 -i,会弹出一个对话框让你设置选项。

撰写回答