python跟踪分段错误
我正在从python开发C扩展,我得到了一些错误(在开发过程中不可避免…)python跟踪分段错误,python,c,debugging,Python,C,Debugging,我正在从python开发C扩展,我得到了一些错误(在开发过程中不可避免…) 我正在寻找一种方法来显示segfault发生在哪一行代码上(一种想法就像跟踪每一行代码),我如何才能做到这一点?下面是一种方法,可以输出代码运行的每一行Python的文件名和行号: import sys def trace(frame, event, arg): print("%s, %s:%d" % (event, frame.f_code.co_filename, frame.f_lineno))
我正在寻找一种方法来显示segfault发生在哪一行代码上(一种想法就像跟踪每一行代码),我如何才能做到这一点?下面是一种方法,可以输出代码运行的每一行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()
输出:
call, test.py:7
line, test.py:8
Line 8
line, test.py:9
Line 9
return, test.py:9
(当然,您可能希望将跟踪输出写入文件。)如果您在linux上,请在gdb下运行python
gdb python
(gdb) run /path/to/script.py
## wait for segfault ##
(gdb) backtrace
## stack trace of the c code
来自C扩展的SEGFULT通常是由于在创建对象的新引用时未增加引用计数而导致的。这使得它们很难跟踪,因为segfault仅在从对象中删除最后一个引用之后发生,甚至通常只有在分配其他对象时才会发生 <>你不会说到目前为止你已经写了多少C扩展代码,但是如果你刚开始考虑你是否可以使用cType或者。Ctypes可能不够灵活,无法满足您的需要,但您应该能够使用Cython链接到几乎任何C库,并自动维护所有引用计数
这并不总是足够的:如果您的Python对象和任何底层C对象有不同的生命周期,您仍然会遇到问题,但它确实大大简化了事情。gdb有一些未记录的Python扩展 从Python源代码抓取(它不包括在正常安装中) 将其放入
sys.path
然后:
这方面的文档记录得有点少,以及
如果您有一个较旧的
gdb
或者就是无法实现这一点,那么Python源代码中也有一个可以复制到~/.gdbinit
,它添加了一些类似的功能我来这里是为了寻找同一问题的解决方案,而其他答案都没有帮助我。帮助的是,您可以使用pip install
在Python2.7中安装它
faulthandler
仅在2012年9月发布的3.3版中才引入Python,这是在这里编写了大多数其他答案之后发布的。如果您已经有了核心文件,您可以使用gdb Python core
(或任何核心文件的名称)。如果您在OSX上,内核转储(默认情况下不生成;请参阅ulimit-c
)存储在目录/cores
中。我真希望这是我的第一个答案,因为阅读所有其他内容花费了相当长的时间,我宁愿花在查找我的bug上。如果在运行Python单元测试时遇到SEGFULT,如Python-m unittest my.module.tests.mytest
,则,然后-m
开关会混淆gdb
。使用--args
选项调用:gdb--args python-m unittest my.module.tests.mytest
类似地使用命令:`gdb--args python3.6-c“import something;something.doStuff();”@标记您的答案对我很有帮助,谢谢!它只是说“没有指定可执行文件”@MadPhysicast:它不会打印C代码的行号,如果这是你的意思的话。:-)它将打印调用C代码的Python代码的行号,这就是我的意思。我发现原来的问题很有趣,因为我也有同样的问题。segfault原来是因为我的C代码在PyList_对象中插入了NULL元素。当我尝试遍历列表时,它在Python端表现出来。不确定python调试器在这种情况下会有多大帮助。为了使输出更易于阅读(并且不会显著降低程序的速度),请使用中提到的faulthandler
模块)--但即使要使用跟踪,也只需使用python的内置跟踪模块(python-m trace--trace test.py
)--但是,这两种方法都不会在C代码中显示回溯。而且,在不属于它们的地方放置空值。很好!若您可以读取Python程序的标准输出,那个么使用起来就像:importfaulthandler;faulthandler.enable()
# 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):
(gdb) python
>import sys
>sys.path.append('/path/to/containing/dir/')
>import libpython
>
>end