如何调试Python分段错误?

112

如何调试Python的分段错误?

我们正在尝试在SuSE 12.3上运行我们的python代码。我们遇到了可重复的分段错误。这个Python代码在其他平台上运行多年,没有出现过分段错误。

我们只编写Python,没有C扩展...

有什么最好的调试方法吗?我知道一点ansi c,但那是十年前的事情...

Python 2.7.5

更新

分段错误发生在解释器关闭时。

我可以运行脚本多次:

python -m pdb myscript.py arg1 arg1
continue
run
continue
run

但是,如果我使用ctrl-d离开pdb,就会出现分段错误。

更新2

我现在尝试使用gdb进行调试:

gdb 
> file python
> run myscript.py arg1 arg2
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffefbe2700 (LWP 15483)]
0x00007ffff7aef93c in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0
(gdb) bt
#0  0x00007ffff7aef93c in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0
#1  0x00007ffff7af5303 in PyEval_EvalCodeEx () from /usr/lib64/libpython2.7.so.1.0
#2  0x00007ffff7adc858 in ?? () from /usr/lib64/libpython2.7.so.1.0
#3  0x00007ffff7ad840d in PyObject_Call () from /usr/lib64/libpython2.7.so.1.0
#4  0x00007ffff7af1082 in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0
#5  0x00007ffff7af233d in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0
#6  0x00007ffff7af233d in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0
#7  0x00007ffff7af5303 in PyEval_EvalCodeEx () from /usr/lib64/libpython2.7.so.1.0
#8  0x00007ffff7adc5b6 in ?? () from /usr/lib64/libpython2.7.so.1.0
#9  0x00007ffff7ad840d in PyObject_Call () from /usr/lib64/libpython2.7.so.1.0
#10 0x00007ffff7ad9171 in ?? () from /usr/lib64/libpython2.7.so.1.0
#11 0x00007ffff7ad840d in PyObject_Call () from /usr/lib64/libpython2.7.so.1.0
#12 0x00007ffff7aeeb62 in PyEval_CallObjectWithKeywords () from /usr/lib64/libpython2.7.so.1.0
#13 0x00007ffff7acc757 in ?? () from /usr/lib64/libpython2.7.so.1.0
#14 0x00007ffff7828e0f in start_thread () from /lib64/libpthread.so.0
#15 0x00007ffff755c7dd in clone () from /lib64/libc.so.6

更新3

我从http://hg.python.org/cpython/file/default/Misc/gdbinit安装了gdbinit,并从http://download.opensuse.org/debug/distribution/12.3/repo/oss/suse/x86_64/下载了调试符号。

(gdb) pystack
No symbol "_PyUnicode_AsString" in current context.

现在怎么做?

更新4 我们安装了一个新的RPM包(python-2.7.5-3.1.x86_64)。我们得到的segmentation fault(分段错误)更少了,但仍然会发生。 这是链接到资源库的链接:

http://download.opensuse.org/repositories/devel:/languages:/python:/Factory/openSUSE_12.3/x86_64/

更新5 解决了我的初始问题:

这是http://bugs.python.org/issue1856(shutdown(exit)可以挂起或与运行的守护线程发生分段错误)

相关:Detect Interpreter shut down in daemon thread

5个回答

84

我看到这个问题是因为出现了分段错误,不只是在退出时出现,而是经常性的出现。我发现没有什么比faulthandler更有效地帮助解决问题。它是Python 3.3的一部分,你可以使用pip安装到2.7中。


18
请说明如何在您的文章中启用故障处理程序,谢谢。 - Jonathan
1
哇,太感谢了!!!我在使用numba和多线程时遇到了段错误,以前从未听说过这个模块。 - Labo
37
只需在 shell 中输入 export PYTHONFAULTHANDLER=1 即可。 - jonas
导出 PYTHONFAULTHANDLER=1 然后 python3 script.py - Bằng Rikimaru

73

Python3用户的简短信息:使用内置模块faulthandler。

首先,从文档中了解到:

faulthandler是自 Python 3.3 版本以来的内置模块。

代码用法:

import faulthandler

faulthandler.enable()
// bad code goes here

Shell 的用法:

$ python3 -q -X faulthandler
>>> /// bad cod goes here

这对于提供宝贵的见解(线程和调用堆栈)非常有帮助,在这种情况下弥补了缺乏适当的Python堆栈跟踪的不足。这仍然需要开发人员进行一些工作,但原始问题是关于调试方法论,而不是实际解决特定崩溃问题(有很多导致段错误的原因)。 - aboellinger
当我尝试使用tox运行测试时,出现了分段错误。将上述代码添加到配置中并没有什么帮助。还有其他调试方法吗? - Underoos

10
也许有一个守护进程正在运行?有一个可重现的错误,该错误已经在3.x中修复,但在2.x中没有修复:

http://bugs.python.org/issue1856:

shutdown (exit) can hang or segfault with daemon threads running

这是我自己问题的答案。找到问题的根源花了一些时间。

下一个问题是:如何编写代码解决这个 bug:检测守护线程中解释器的关闭


我也在关闭应用程序时遇到了段错误。如何为Python 2.7纠正这个错误? - Patrick

10

如上所述,您可以使用faulthandler来完成此操作。例如:

import faulthandler; faulthandler.enable()

在你的import语句附近添加这行代码并运行。它将帮助你调试,或尝试显示导致段错误的最近一行代码。然后你可以根据需要进行更改。


2
需要在开头或任何地方添加这行代码吗?我们还需要做其他事情吗? - Ashba jawed

6
如果您只执行Python代码(即使是通过导入的第三方模块),那么段错误可能意味着解释器或其内置的C模块中存在错误。您可以构建CPython并尝试自己调试,或尝试生成最小的脚本来重现崩溃,并提交问题

1
虽然 C 错误可能来自模块错误(例如 TensorFlow)或编译不当的模块,但这是真的。 - borgr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接