错误c0000374含义及解决:MinGW编译DLL清理阶段崩溃
程序清理阶段崩溃(错误c0000374)排查与解决
问题概述
程序在清理阶段崩溃,触发错误Critical error detected c0000374,该错误通常指向内存损坏。但代码仅使用自动管理的std::stringstream及简单自定义对象,无复杂堆分配操作。GDB调试显示,在输出Destruct Foo后触发崩溃,调用栈如下:
#0 0x00007fffa662f3a3 in ntdll!RtlIsZeroMemory () from C:\WINDOWS\SYSTEM32\ntdll.dll #1 0x00007fffa6638162 in ntdll!RtlpNtSetValueKey () from C:\WINDOWS\SYSTEM32\ntdll.dll #2 0x00007fffa663844a in ntdll!RtlpNtSetValueKey () from C:\WINDOWS\SYSTEM32\ntdll.dll #3 0x00007fffa663e0d1 in ntdll!RtlpNtSetValueKey () from C:\WINDOWS\SYSTEM32\ntdll.dll #4 0x00007fffa6555bf0 in ntdll!RtlGetCurrentServiceSessionId () from C:\WINDOWS\SYSTEM32\ntdll.dll #5 0x00007fffa65547b1 in ntdll!RtlFreeHeap () from C:\WINDOWS\SYSTEM32\ntdll.dll #6 0x00007fffa6279c9c in msvcrt!free () from C:\WINDOWS\System32\msvcrt.dll #7 0x00007fff72772ef0 in std::locale::_Impl::~_Impl() () from D:\mypath\lib\libfoo.dll #8 0x00007fff72771ce3 in std::locale::_Impl::_M_remove_reference() () from D:\mypath\lib\libfoo.dll #9 0x00007fff7271131b in bar::Foo::~Foo (this=0xa111dffa40, __in_chrg=<optimized out>)
最小复现代码
script.cpp
#include <foo.hpp> int test_foo(){ bar::Foo foo; return 0; }
foo.hpp
namespace bar{ class Foo{ public: std::stringstream ss; ~Foo(); }; }// namespace bar
foo.cpp
namespace bar{ Foo::~Foo(){ printf("Destruct Foo\n"); } }// namespace bar
补充信息:原程序更复杂,已精简至上述最小案例。代码合并到单个文件时无崩溃,推测为DLL相关问题。环境:Windows 10、MinGW、GCC 12.2.0、CMake 3.21.0。
排查与解决思路
- 统一标准库链接方式:MinGW下,DLL与主程序必须使用相同的C++标准库链接策略。若DLL动态链接标准库(默认),主程序也需动态链接;若要避免跨模块堆冲突,建议两者均静态链接标准库——编译时添加
-static-libstdc++ -static-libgcc选项,确保std::locale等标准库对象的分配与释放在同一模块内完成。 - 检查CMake配置一致性:
- 在DLL的CMakeLists.txt中,确保添加
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -shared -fPIC")以生成正确的动态库。 - 主程序与DLL的CMake配置需同步所有编译选项(如C++标准版本、优化级别、宏定义),避免对象内存布局不一致引发的内存损坏。
- 在DLL的CMakeLists.txt中,确保添加
- 启用内存检测:编译时添加
-fsanitize=address启用AddressSanitizer,可精准定位跨模块内存操作的错误点,帮助快速定位问题根源。 - 检查DLL导出/导入正确性:确保自定义类的析构函数等关键函数在DLL中正确导出,避免主程序调用错误的析构实现。
内容的提问来源于stack exchange,提问作者Qwert Yuiop
相关产品推荐
相关产品推荐

