Windows 下 Python 3 出 segfault 时如何找错?

2017-07-01 10:29:28 +08:00
 yucongo

请教各位在 Windows 下 Python 3 出 segfault 时如何有效地找错。

Linux 下有 gdb。Windows 下 MinGW 的 gdb-python 好像只能用在 Python 2 上。我的程序是用 Python 3 写的,很多自己写的函数,2to3 应付不了,手动改要花很多时间。有在 qq 群里问过,有人建议用二分法删源码,直到 segment fault 不再出现就找到错了。这种方法好像效率太低,而且如果 segment fault 不是固定出现在某的地方不可用。

GUI 下用个 thread、pubsub 什么的,出 segfault 还是比较常见的,而且 GUI ( pyqt,wxpython 之类的)程序的 Test 测试好像也没有什么好的办法,unitest、pytes 派不太上用场。各路高手用什么方法找导致 segfault 的错误?请分享一下,先感谢。

3601 次点击
所在节点    Python
20 条回复
dbow
2017-07-01 10:34:39 +08:00
完整的错误信息贴出来看看。
yucongo
2017-07-01 10:40:03 +08:00
@dbow 出 segfault 是没有错误信息的,整个 python 死掉。
ipwx
2017-07-01 10:42:56 +08:00
Python 出 Segment Fault 一般不是 Python 写的代码的问题。

你写的、或者你引用的 native package 有问题。删掉整个 Python 3 重新安装一下吧?另外二进制的包如果用 Anaconda 装,一般会降低出问题的概率。
dbow
2017-07-01 10:47:45 +08:00
gdb --args ./app ..... 跑一遍, 出了 segment fault, 用 bt 命令, 输出 stack trace
yucongo
2017-07-01 10:56:02 +08:00
感谢楼上 @ipwx、 @dbow 二位。

不管是 native package 还是代码问题,都是想先找到出错的原因。gdb 貌似不能给出出错的 python 源码位置。看 stackoverflow 里说,gdb-python 倒是可以给出 python 源码位置。但 gdb-python 在 windows 里只能用于 Python 2. 我已经花了一天试着将我的 Python 3 改成 Python 2. 太麻烦、太乱,只好放弃。
XYxe
2017-07-01 11:07:46 +08:00
@yucongo #5 用 VS 来编译 Python,然后参数加上你要运行的 Python 代码,应该可以定位到错误位置。
yucongo
2017-07-01 11:15:12 +08:00
@XYxe 感谢。先记下来研究一下。VS 好像太大了,而且我的机器比较旧,怕是拖不动 VS。
ipwx
2017-07-01 11:22:47 +08:00
@yucongo 你把你装的依赖包列一下我们看看吧。很可能某个第三方库的二进制包和你的 Python 二进制不太兼容…… 或者你的代码使用第三方库时导致了它内部二进制包的异常。

另外最后的出错信息打出来看看也很重要。第三方库的二进制包出问题的 stack trace 和 Python 自己的二进制包出错,信息还是不一样的。
congeec
2017-07-01 11:39:58 +08:00
gdb-python 可以用于 python 3,不过你得自己编译安装。我试过,挺麻烦
yucongo
2017-07-01 12:02:26 +08:00
@congeec 感谢提供信息。我想我会用 MinGW 试试。如果你有有关资料能提供一些链接什么的就更加感谢了。
yucongo
2017-07-01 12:10:47 +08:00
certifi==2017.4.17
chardet==3.0.2
colorama==0.3.9
configobj==5.0.6
cx-Freeze==5.0.2
future==0.16.0
googletrans==2.1.3
html2text==2016.9.19
langdetect==1.0.7
langid==1.1.6
lxml==3.7.3
nltk==3.2.2
nose==1.3.7
numpy==1.13.0
pandas==0.20.2
py==1.4.34
pycountry==17.1.8
pysrt==1.1.1
pysubs2==0.2.1
pytest==3.1.2
python-dateutil==2.6.0
python-docx==0.8.6
pytz==2017.2
pywin32==221
PyYAML==3.12
regex==2017.4.29
requests==2.13.0
requests-cache==0.4.13
segtok==1.5.5
six==1.10.0
textblob==0.12.0
tqdm==4.11.2
wxPython==4.0.0a2.dev3016+2645796
xlrd==1.0.0
yandex.translate==0.3.5

@ipwx Python 3.5 venv 下 pip freeze 的包

因为看不懂 stack trace,所以一直在整 gdb-python,不过我试着用 gdb 在 Python 3 下获取 stack trace,成功的话在贴上来。
zk8802
2017-07-01 12:11:54 +08:00
用 WinDBG 跑 Python,挂了之后输入 k 看一下调用栈,一般就知道是哪个库的问题了。如果问题不复杂,这可能是最快的方法。
yucongo
2017-07-01 12:55:29 +08:00
@zk8802 感谢。我试试……
congeec
2017-07-01 13:06:40 +08:00
@yucongo https://github.com/fedora-python/python3/blob/master/python-gdb.py
https://wiki.python.org/moin/DebuggingWithGdb
https://docs.python.org/devguide/gdb.html
你需要单独编译 gdb 和 CPython。编译 gdb 的时候,加--with-python="${the directory in which your python3 binary is installed}"。编译一份 CPython,记得用 debug 模式,这样调试时 step 到标准库,也会显示源码的
ipwx
2017-07-01 13:55:41 +08:00
库我认不全,不过我认知的库里面,NumPy, wxPython 和 lxml 都有 native binary。也许应该注意一下。
yucongo
2017-07-02 01:24:11 +08:00
貌似 Windows 下 Python 3 要找 segfault 出错的地方没有什么办法。再加上我的程序还是 wxpython GUI,完全没辙。我试过 Windbg,winpdb,trepan3k,pudb, 都不行。

Windbg 里用 pykd 可以运行 python 非 GUI 程序,运行 wxpython 写的 gui 程序就出不来 gui。也可以在 python 下运行 wxpython 写的 gui 程序后 attach 到 Windbg, 但 attach 后 wxpython gui 就没有反应了, 也就是说没法 gui 里的交互(点击、载入文件啊什么的)。

最后还是靠 logging …… 找到 python 一个 bug:

os.startfile("")

python ( 2.7, 3.4, 3.5 )直接死掉。try... except ... 没有用…… 花掉我一整天 ……&¥……%¥#
nickr
2017-07-02 08:00:56 +08:00
” Windbg 里用 pykd 可以运行 python 非 GUI 程序,运行 wxpython 写的 gui 程序就出不来 gui。“

这个尝试完全是晕了头. pykd 是 windbg 的一个插件. 在 windbg 里跑起来一个 python vm, 用来和 windbg 交互. 和 op 现在遇到的 python crash 八杆子打不着.
yucongo
2017-07-02 12:28:23 +08:00
这个 os.startfile("") 导致 python.exe 崩溃其实只在 ConEmu 下才出现(我的是 32 位 Windows 7,ConEmu 161002 ),所以可能要算 ConEmu 的 bug 吧……
yucongo
2017-07-02 13:09:05 +08:00
@nickr 感谢回答。

我搞不太清楚。不过 Windbg 里 如果不 !load pykd.dll 是运行不了 !py 的。

Windbg 里 Alt-1:
0:000> !py -3.4
No export py found
0:000> !load pykd.dll
0:000> !py -3.4
Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
hasdream
2017-07-02 21:11:37 +08:00
segfault 报错很多是 C 扩展不支持多线程操作, 比如多线程对一个 mysql(mysqldb)连接发起查询请求就会这样(每个线程开一个连接去查询就可以解决这个问题)。 大部分是 C 扩展一个回话不支持多线程操作 或者操作需要加锁

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/372298

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX