1

我正在使用 Visual Studio 2010 在 C++ 中开发 Win32 应用程序。在调试模式下运行时,应用程序运行良好并在退出时正确关闭。然而,在发布时,程序运行良好,但在应用程序关闭时出现未处理的异常:Application.exe 中 0x009C19F5 处的未处理异常:0xC0000005:访问冲突读取位置 0x00297628。

然后调试器在 std::local 的析构函数中中断 xlocale:

~locale() _THROW0()
{  // destroy the object
if (_Ptr != 0)
    _DELETE_CRT(_Ptr->_Decref()); // breaks here with unhandled exception
}

我相信,在我的 main 函数返回并在某处调用 exit(0) 之后,上面的代码正在运行。这是我崩溃时的调用堆栈:

Application.exe!std::locale::~locale() Line 411 C++
Application.exe!doexit(int code, int quick, int retcaller) Line 567 C
Application.exe!exit(int code) Line 393 C
Application.exe!__tmainCRTStartup() Line 284    C
kernel32.dll!@BaseThreadInitThunk@12()  Unknown
ntdll.dll!___RtlUserThreadStart@8() Unknown
ntdll.dll!__RtlUserThreadStart@8()  Unknown

我正在使用 Microsoft 的应用程序验证程序,并且正在运行 _CrtCheckMemory( ); 经常检查堆损坏,我没有看到在调试或发布模式下检测到任何东西。在我的任何来源中,我也根本没有弄乱 std::locale 。

我最近将解决方案的设置切换为默认使用 unicode 而不是 256 个一字节大小的字符。但是,现在在 unicode 和多字节设置之间来回切换似乎不会影响发布时退出时的崩溃。

有谁知道发生了什么?

4

2 回答 2

0

我找到了解决方案。有一些全局变量调用 new 并且我有 new 重载。当第一次调用 new 时,会构建自定义内存管理器。这很好,但是在程序关闭时,一些对象会在内存管理器之后销毁。破坏顺序是造成问题的原因。

于 2013-03-04T04:39:40.057 回答
0

具有相同症状的崩溃的另一个可能原因是由以下微妙注释描述的行为引起的:

重载 7 (即locale(const locale& other, Facet* f)通常用它的第二个参数 调用,f直接从一个新表达式获得:语言环境负责delete从它自己的析构函数调用匹配。

这似乎暗示语言环境只有在它来自时才会删除构面new,但实际上它不会。换句话说,一个语言环境是从一个不是由 构建的构面构造的new,或者是之前被删除的,从而导致语言环境析构函数的崩溃delete

这可以通过给区域设置适当的刻面绝对所有权来解决,即不手动删除刻面或让任何智能指针自动执行(以及确保它实际上是通过 构造的new),或者,如果修改刻面是可能,超载delete

于 2021-10-05T12:55:14.100 回答