记一次 .NET Core 程序崩溃问题修复
背景:程序使用 ONNX Runtime 运行AI模型推理,但是仅能使用CPU执行,一旦想使用支持GPU版本的包"Microsoft.ML.OnnxRuntime.DirectML",程序就卡住一会然后崩溃。
引发崩溃的代码如下:
int gpuDeviceId = 0;
var sessionOptions = new SessionOptions()
{
LogSeverityLevel = OrtLoggingLevel.**ORT_LOGGING_LEVEL_WARNING**,
};
sessionOptions.AppendExecutionProvider_DML(gpuDeviceId);
sessionOptions.GraphOptimizationLevel = GraphOptimizationLevel.**ORT_ENABLE_ALL**;\
var inferenceSession = new InferenceSession(**modelParh**, sessionOptions);
经过排查,如果使用一个纯净的新项目运行上面代码(同样的 .NET 版本和 ONNX 包版本),可以运行,但是在原项目里就是不行。
并且,为了消除是其它什么地方意外修改了啥导致出现问题,把这段引起崩溃的代码放到Program.cs的 Main函数在程序启动时就执行,也是崩溃。
那么,难道是依赖项导致的问题?这是有可能的,因为ONNX Runtime会使用native的dll,native dll之间发生版本冲突是会导致奇怪问题。
于是使用 WinDBG 分析程序崩溃转储文件"XXXX.Application.Host.exe.dmp",最后的堆栈是:
STACK_TEXT:
00000064`04978160 00007ffc`8ed4c4cc : 0000025f`00000001 0000025f`17fc39f8 0000025f`17fc39f8 0000025f`17fc3a00 : msvcp140!mtx_do_lock+0x9c
00000064`049781c0 00007ffc`8ed59105 : 00007ffc`8efb1de8 00000064`04978638 0000025f`17fc39f8 00000000`00000001 : onnxruntime!OrtSessionOptionsAppendExecutionProvider_CPU+0x63d7bc
00000064`04978210 00007ffd`aaa9526d : 00000000`00000007 00000000`00000000 00000000`00000000 00007ffd`ad02bfca : onnxruntime!OrtSessionOptionsAppendExecutionProvider_CPU+0x64a3f5
00000064`04978240 00007ffc`8ed639ea : 00000000`00000000 00000000`7ffe0384 00000064`04978638 00007ffd`acfd8b68 : ucrtbase!initterm+0x2d
00000064`04978270 00007ffc`8ed63b57 : 00000000`00000001 00000000`00000000 00000000`00000000 00000000`00000001 : onnxruntime!OrtSessionOptionsAppendExecutionProvider_CPU+0x654cda
00000064`049782a0 00007ffd`acfd8b5f : 00007ffc`8e430000 00000000`00000001 00000000`00000000 00000000`7ffe0385 : onnxruntime!OrtSessionOptionsAppendExecutionProvider_CPU+0x654e47
00000064`04978300 00007ffd`ad01d4fd : 0000025f`001519c0 00007ffc`8e430000 00007ffc`00000001 00000000`00000000 : ntdll!LdrpCallInitRoutine+0x6b

在对msvcp140的函数调用中出现了崩溃,是指针异常引发的崩溃,为什么当前项目调用这里会崩,而纯净项目不会?于是拿纯净项目输出的bin\runtimes\win-x64文件夹和当前项目一一比对:发现纯净项目下没有msvcp140.dll文件
于是,我试着再次启动原项目,但启动前删除了msvcp140.dll文件,于是好了!
也就是说,原项目有别的地方依赖了msvcp140.dll库,导致这个dll被拷贝到了程序目录,而msvcp140.dll是一个C++运行时,我的系统已经安装过,因此即使程序目录下没有,也会自动去系统安装目录找到并加载;但是由于我程序目录有了,它从当前目录加载;
那么可能ONNX的GPU版刚好也依赖msvcp140.dll,但是dll版本有细微差异,导致了内部指针异常。
最终经过排查,也确实如此,尝试升级了项目对msvcp140.dll的依赖版本后,问题解决。
浙公网安备 33010602011771号