pyg*_*iel 49 c python debugging
我正在从python ad开发C扩展我获得了一些段错误(在开发过程中不可避免......).
我正在寻找一种方法来显示段错误发生在哪一行代码(一个想法就像跟踪每一行代码),我该怎么做?
Mar*_*ark 72
如果你在linux上,在gdb下运行python
gdb python
(gdb) run /path/to/script.py
## wait for segfault ##
(gdb) backtrace
## stack trace of the c code
Run Code Online (Sandbox Code Playgroud)
Ric*_*dle 38
这是一种输出代码运行的每一行Python的文件名和行号的方法:
import sys
def trace(frame, event, arg):
print("%s, %s:%d" % (event, frame.f_code.co_filename, frame.f_lineno))
return trace
def test():
print("Line 8")
print("Line 9")
sys.settrace(trace)
test()
Run Code Online (Sandbox Code Playgroud)
输出:
call, test.py:7
line, test.py:8
Line 8
line, test.py:9
Line 9
return, test.py:9
Run Code Online (Sandbox Code Playgroud)
(当然,您可能希望将跟踪输出写入文件.)
Dun*_*can 17
C扩展中的Segfaults通常是在创建对象的新引用时不增加引用计数的结果.这使得它们很难跟踪,因为只有在从对象中删除最后一个引用之后才会发生段错误,甚至通常只有在分配了其他对象时才会发生.
你没有说到目前为止你写了多少C扩展代码,但如果你刚开始考虑是否可以使用ctypes或Cython.Ctypes可能不够灵活,无法满足您的需求,但您应该能够使用Cython链接到任何C库,并自动为您维护所有引用计数.
这并不总是足够的:如果您的Python对象和任何底层C对象具有不同的生命周期,您仍然可以遇到问题,但它确实大大简化了事情.
我来到这里寻找同一问题的解决方案,其他答案都没有帮助我.帮助是什么faulthandler,你只需使用它就可以在Python 2.7中安装它pip install.
faulthandler 仅在版本3.3中引入了Python,该版本于2012年9月发布,这是在此处的大多数其他答案之后编写的.
gdb 有一些未记录的 python 扩展。
来自 Python 源代码Tools/gdb/libpython.py(它不包含在正常安装中)。
把这个放进去sys.path
然后:
# gdb /gps/python2.7_x64/bin/python coredump
...
Core was generated by `/usr/bin/python script.py'.
Program terminated with signal 11, Segmentation fault.
#0 call_function (oparg=<optimized out>, pp_stack=0x7f9084d15dc0) at Python/ceval.c:4037
...
(gdb) python
>import libpython
>
>end
(gdb) bt
#0 call_function (oparg=<optimized out>, pp_stack=0x7f9084d15dc0) at Python/ceval.c:4037
#1 PyEval_EvalFrameEx (f=f@entry=
Frame 0x7f9084d20ad0,
for file /usr/lib/python2.7/site-packages/librabbitmq/__init__.py, line 220,
in drain_events (self=<Connection(channels={1: <Channel(channel_id=1, connection=<...>, is_open=True, connect_timeout=4, _default_channel=<....(truncated), throwflag=throwflag@entry=0) at Python/ceval.c:2681
...
(gdb) py-list
218 else:
219 timeout = float(timeout)
>220 self._basic_recv(timeout)
221
222 def channel(self, channel_id=None):
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我们现在可以看到与 CPython 调用链相对应的 Python 堆栈。
一些注意事项:
--with-pythongdb嵌入 python (通过链接到libpython),它不会在子 shell 中运行它。这意味着它可能不一定与上的 python 版本匹配$PATH。libpython.py任何版本匹配的 Python 源代码下载。gdbsys.path以匹配您正在调试的代码。如果您无法复制libpython.py到,sys.path那么您可以将其位置添加到sys.path如下所示:
(gdb) python
>import sys
>sys.path.append('/path/to/containing/dir/')
>import libpython
>
>end
Run Code Online (Sandbox Code Playgroud)
这在python 开发文档、fedora wiki和python wiki中记录得很少。
如果您有较旧的版本gdb或无法正常工作,Python 源代码中还有一个gdbinit~/.gdbinit ,您可以将其复制到其中添加一些类似的功能