Python C扩展调用FFmpeg出现Segmentation fault但独立C程序正常的原因
问题触发原因分析
1. 全局符号冲突
- FFmpeg的libav系列库存在大量全局状态,Python进程启动后可能已经加载了其他依赖FFmpeg的库(如
opencv-python、ffmpeg-python底层绑定),和你的扩展链接的FFmpeg 3.4.8版本符号冲突,全局变量被篡改导致段错误。 - 纯C测试程序启动时只加载你的扩展so,没有其他冲突符号,所以运行正常。
2. GIL操作逻辑错误
- 如果你在
convertVideo函数执行耗时操作前主动释放了GIL,但后续代码中又调用了Python的C API(如日志输出、参数读取),会触发非法内存访问。 - 纯C测试程序不涉及Python GIL机制,所以不会触发该问题。
3. 参数传递校验缺失
- Python层传入
convert_video的参数类型校验缺失,比如传入的字符串路径没有正确转成C的const char*,你直接读取了非法内存地址;C测试程序直接传入合法C字符串,所以没有问题。 - 常见错误场景:没有对
PyArg_ParseTuple的返回值做校验,参数解析失败时后续代码仍读取了未初始化的指针变量。
4. 栈空间不足
convertVideo函数内存在栈上分配大内存块的逻辑(如声明了大小为几MB的数组),Python进程的默认栈大小比纯C程序小,触发栈溢出段错误。- 纯C测试程序默认栈空间更大,刚好能容纳你的大内存分配,所以运行正常。
5. 信号处理逻辑冲突
- FFmpeg内部会注册部分信号处理函数,Python进程自身也有信号处理逻辑(如SIGSEGV的处理、超时信号等),两者冲突导致信号触发时执行了非法的处理函数。
- 纯C测试程序没有Python的信号处理逻辑,所以不会触发冲突。
快速验证方案
- 启动Python时添加
-s参数禁用用户site包,避免其他第三方库加载冲突FFmpeg符号 - 给
PyArg_ParseTuple加返回值校验,所有参数解析失败时直接抛出Python异常返回 - 注释掉所有GIL释放逻辑,单线程运行测试是否还会段错误
- 把函数内栈上分配的大数组改成
malloc动态分配
内容的提问来源于stack exchange,提问作者Christian Vorhemus
相关产品推荐
相关产品推荐

