如何调试 Python 内存区段错误?

如何调试 Python 内存区段错误?

我们试图在 SuSE 12.3上运行 Python 代码。我们得到可重复的分段故障。多年来,python 代码一直在其他平台上工作,没有出现分段错误。

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

调试这个程序的最佳方法是什么?我知道一点,但那是十年前的事了。

Python 2.7.5

更新

解释器关闭时会出现内存区段错误。

我可以多次运行这个脚本:

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

但是如果将 pdb 保留为 ctrl-d,就会出现分割错误。

更新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

我从 < a href = “ http://hg.python.org/cpython/file/default/misc/gdbinit”rel = “ norefrer”> 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.

现在怎么办?

我们安装了一个新的 RPM (python-2.7.5-3.1. x86 _ 64)。 下面是到存储库的链接:

Http://download.opensuse.org/repositories/devel:/languages:/python:/factory/opensuse_12.3/x86_64/

解决了我最初的问题:

它是 http://bugs.python.org/issue1856(关闭(退出)可以挂起或者使守护进程线程运行的 Segfault)

相关阅读: 在守护进程线程中检测解释程序关闭

112833 次浏览

If you're executing nothing but Python code (even through your imported third party modules), than a segfault probably means there's a bug in the interpreter or one of its builtin C modules.

You can either build CPython and try to debug it yourself, or try to produce the smallest script which reproduces the crash and file an issue.

Maybe there is a daemon thread running? There is a reproduceable bug, which was fixed only for 3.x, but not for 2.x:

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

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

This is the answer to my own question. It took some time to find the root of the problem.

Here is the next question: How to code around this bug: Detect Interpreter shut down in daemon thread

I got to this question because of the Segmentation fault, but not on exit, just in general, and I found that nothing else helped as effectively as faulthandler. It's part of Python 3.3, and you can install in 2.7 using pip.

tl;dr for python3 users.

Firstly, from the docs:

faulthandler is a builtin module since Python 3.3

Code usage:

import faulthandler


faulthandler.enable()
// bad code goes here

Shell usage:

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

You can do this with faulthandler as mentioned. E.g.

import faulthandler; faulthandler.enable()

Just add this line near your import statement and run the code. It will help to debug you or will try to show you nearest line in your code which caused the segmentation fault. Then you can make changes wherever required.