如何排查Python程序每日出现的Segmentation fault问题?
定位Python程序Segmentation Fault问题的实用步骤
一、先搞定核心转储(core dump)缺失问题
提示core dumped但找不到文件,先配置系统生成core文件:
- 检查当前core文件大小限制:执行
ulimit -c,如果输出0就是禁用状态,临时开启用ulimit -c unlimited;要永久生效,编辑/etc/security/limits.conf,添加两行:
之后重启会话生效。* soft core unlimited * hard core unlimited - 确认core文件存储路径:执行
sysctl kernel.core_pattern查看,要是输出类似|/usr/share/apport/apport %p %s %c %d %P,说明被系统工具拦截了。临时修改用sysctl -w kernel.core_pattern=core.%p(生成带进程ID的core文件,避免覆盖);永久修改编辑/etc/sysctl.conf,添加kernel.core_pattern=core.%p,再执行sysctl -p生效。
二、用GDB分析核心转储文件
拿到core文件后,直接加载分析:
- 执行
gdb python3 core.xxx(替换成实际的core文件名) - 进入GDB后,输入
bt full查看完整调用栈,能直接看到崩溃发生的底层函数。如果调用栈里出现QWidget、QEventLoop这类PyQt5相关的C函数,基本能锁定是PyQt5的问题。
三、拿不到core dump时的替代排查法
如果还是没法生成core文件,用这些方法:
- 直接用GDB运行程序:执行
gdb --args python3 your_program.py,输入run启动程序,等崩溃后输入bt查看调用栈,效果和分析core文件一致。 - 用Valgrind检测内存问题:Valgrind能抓C扩展的内存泄漏、越界访问,执行
valgrind --leak-check=full python3 your_program.py,输出里的C层面错误提示,大概率是问题根源。 - 启用Python的faulthandler:在程序开头加两行代码,Segfault时会打印Python层面的调用栈,帮你定位哪段Python代码触发了底层崩溃:
import faulthandler faulthandler.enable()
四、针对PyQt5的专项排查
既然怀疑PyQt5,重点检查这几点:
- 核对PyQt5版本:对比之前稳定运行时的版本,有没有最近升级过?回退到旧版本测试,比如
pip install pyqt5==你之前用的稳定版本号。 - 检查UI线程规范:PyQt5要求所有UI操作必须在主线程执行,子线程直接操作控件(比如往QTextEdit写日志)必崩。检查代码里有没有子线程直接调用UI方法,改用
QMetaObject.invokeMethod或者信号槽跨线程更新。 - 排查资源释放问题:有没有未正确销毁的Qt对象?或者循环引用导致内存泄漏?可以在程序里定期调用
gc.collect(),并检查Qt对象的isValid()状态。 - 写最小复现程序:把PyQt5相关的日志UI逻辑单独抽出来,写个极简版程序测试,逐步添加其他功能,缩小问题范围。
内容的提问来源于stack exchange,提问作者ullix
相关产品推荐
相关产品推荐

