提取ONNX Runtime会话为函数触发Segmentation Fault问题排查
问题原因分析
核心问题出在Ort::Session依赖对象的生命周期不匹配,具体细节如下:
错误写法的触发逻辑
当你把Session创建逻辑封装到newSess函数时,大概率是在函数内部声明了Ort::Env、Ort::SessionOptions这类Session的必要依赖对象——它们是函数的局部变量。函数执行完毕返回Session对象后,这些局部变量会被自动销毁,底层关联的系统资源也会被释放。但Ort::Session内部会持有对这些资源的引用,后续调用Run方法时,程序会尝试访问已经被释放的内存空间,直接触发Segmentation Fault。main函数正常的原因
在main里直接写全部逻辑时,Ort::Env、Ort::SessionOptions和Ort::Session处于同一个作用域,它们的生命周期完全同步——直到程序结束才会被销毁。Session调用Run时,所有依赖的资源都还处于有效状态,所以能正常执行。
错误代码示例(导致段错误的写法)
Ort::Session newSess(const std::string& model_path) { Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "test"); Ort::SessionOptions session_options; return Ort::Session(env, model_path.c_str(), session_options); } int main() { auto ort_session = newSess("model.onnx"); // 此时env和session_options已被销毁,调用Run触发段错误 ort_session.Run(...); return 0; }
修正后的正确写法
方式1:将依赖对象提升到外层作用域传入
Ort::Session newSess(Ort::Env& env, const std::string& model_path) { Ort::SessionOptions session_options; return Ort::Session(env, model_path.c_str(), session_options); } int main() { Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "test"); auto ort_session = newSess(env, "model.onnx"); ort_session.Run(...); // 依赖对象存活,正常执行 return 0; }
方式2:封装成类统一管理生命周期
class ModelRunner { private: Ort::Env env; Ort::Session session; public: ModelRunner(const std::string& model_path) : env(ORT_LOGGING_LEVEL_WARNING, "test"), session(env, model_path.c_str(), Ort::SessionOptions{}) {} void run(...) { session.Run(...); } }; int main() { ModelRunner runner("model.onnx"); runner.run(...); return 0; }
内容的提问来源于stack exchange,提问作者chikadance
相关产品推荐
相关产品推荐

