使用pybind11导入onnx模块时出现段错误(Segmentation fault)的求助
解决pybind11导入onnx触发段错误的问题
先查Python版本是否匹配
- 很多段错误根源在于C++程序链接的Python版本,和pip安装onnx用的版本不匹配。先跑
python3 --version确认版本,编译时要指定对应版本的头文件和库——比如CMake里把Python_EXECUTABLE设成你使用的Python路径。 - 用
pip show onnx查看onnx的安装路径,确认该路径下的Python版本和程序依赖的完全一致。要是版本不符,就用对应版本的pip重装,比如python3.10 -m pip install onnx。
检查编译器ABI兼容性
- 若你程序的编译器和onnx编译时用的ABI不兼容,必然会出问题。比如onnx是GCC编译的,就别用Clang编译你的程序(除非ABI版本一致)。Linux下重点关注
_GLIBCXX_USE_CXX11_ABI宏:onnx编译时如果设置了-D_GLIBCXX_USE_CXX11_ABI=0,你的程序也要跟着设相同参数,反之亦然。 - 想查看onnx的编译参数?执行
objdump -x $(python -c "import onnx; print(onnx.__file__)"),对比它的依赖库和编译标志与你程序的参数是否一致。
别静态链接Python库
- 要是你的程序是静态链接Python库,赶紧改成动态链接。onnx的C扩展依赖动态Python库,静态链接会引发符号冲突,直接触发段错误。CMake里要确保
Python_LIBRARIES指向动态库(比如libpython3.x.so),别用.a后缀的静态库。
手动加载onnx的依赖库
- 有时候onnx依赖的库没被正确加载,你可以在导入onnx前手动加载相关库。比如在C++代码中添加:
编译时别忘了加#include <dlfcn.h> // 路径要换成你系统中实际的protobuf库路径,按需调整 dlopen("/usr/local/lib/libprotobuf.so", RTLD_LAZY | RTLD_GLOBAL);-ldl链接选项。
实在不行就从源码编译onnx
- 要是上面的方法都没用,就自己编译onnx源码,确保和你的程序环境完全一致:
- 克隆仓库:
git clone --recursive https://github.com/onnx/onnx.git - 进入目录:
cd onnx - 用对应Python版本的pip从源码安装:
python -m pip install -e . --no-binary onnx - 需要指定ABI参数的话,就加CMAKE_ARGS:
CMAKE_ARGS="-D_GLIBCXX_USE_CXX11_ABI=0" python -m pip install -e . --no-binary onnx
- 克隆仓库:
加异常捕获看详细错误
- 可以在C++代码里添加Python异常捕获,说不定能拿到更具体的错误信息,而不是直接触发段错误:
有时候段错误是Python层面的错误未被捕获导致的,这个方法能帮你定位问题。try { auto onnx_module = py::module::import("onnx"); } catch (const py::error_already_set& e) { std::cerr << "Python错误信息: " << e.what() << std::endl; std::cerr << "调用栈: " << e.traceback() << std::endl; }
内容的提问来源于stack exchange,提问作者JSong
相关产品推荐
相关产品推荐

