如何调试 Python 分段错误?

Posted

技术标签:

【中文标题】如何调试 Python 分段错误?【英文标题】:How to debug a Python segmentation fault? 【发布时间】:2013-05-19 19:51:34 【问题描述】:

我们正在尝试在 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)。我们得到的段错误更少,但它们仍然会发生。 这是存储库的链接:

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

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

它是http://bugs.python.org/issue1856(关闭(退出)可能会挂起或在守护线程运行时出现段错误)

相关:Detect Interpreter shut down in daemon thread

【问题讨论】:

【参考方案1】:

由于Segmentation fault,我遇到了这个问题,但不是在退出时,只是一般情况下,我发现没有什么比faulthandler 更有效。它是 Python 3.3 的一部分,您可以使用 pip 在 2.7 中安装。

【讨论】:

请在您的帖子中说明如何启用故障处理程序,谢谢。 天啊,非常感谢!!!我有一个 numba 和多线程的段错误,并且从未听说过这个模块。 只需在 shell 中导出 PYTHONFAULTHANDLER=1。【参考方案2】:

tl;dr 适用于 python3 用户。

首先,来自文档:

faulthandler 是 Python 3.3 以来的内置模块

代码用法:

import faulthandler

faulthandler.enable()
// bad code goes here

外壳用法:

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

【讨论】:

这通过提供宝贵的见解(线程和调用堆栈)证明是有帮助的,弥补了在那种情况下缺乏适当的 python 堆栈跟踪。它仍然给开发人员留下了一些工作,但最初的问题是关于调试方法,而不是实际解决特定的崩溃(有很多道路导致段错误)【参考方案3】:

也许有一个守护线程正在运行?有一个可重现的错误,仅在 3.x 中修复,但在 2.x 中未修复:

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

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

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

这是下一个问题:如何解决这个错误:Detect Interpreter shut down in daemon thread

【讨论】:

我在关闭我的应用程序时也遇到了段错误。如何为 python 2.7 纠正这个错误?【参考方案4】:

您可以使用前面提到的故障处理程序来执行此操作。例如

import faulthandler; faulthandler.enable()

只需将此行添加到您的 import 语句附近并运行代码。这将有助于调试您或尝试在您的代码中显示最近导致分段错误的行。然后,您可以根据需要进行更改。

【讨论】:

在开头或任何地方添加这一行?我们是否需要做其他事情?【参考方案5】:

如果您只执行 Python 代码(即使通过导入的第三方模块),那么段错误可能意味着解释器或其内置 C 模块之一存在错误。

您可以build CPython and try to debug it yourself,或尝试生成重现崩溃的最小脚本和file an issue。

【讨论】:

正确,尽管 c 错误可能来自模块错误(例如 TensorFlow)或错误编译的模块

以上是关于如何调试 Python 分段错误?的主要内容,如果未能解决你的问题,请参考以下文章

分段错误,不确定来源

python跟踪分段错误

如何修复 C++ 中的“分段错误”错误

线程示例,分段错误

为啥我的字符串分配会导致分段错误?

仅在不使用调试器时出现段错误