2

在我的主要结尾处我遇到了一个奇怪的访问冲突,我很难找到原因。

关闭我的应用程序时,我遇到以下访问冲突:

xdebug

        // TEMPLATE FUNCTION _DebugHeapDelete
template<class _Ty>
    void __CLRCALL_OR_CDECL _DebugHeapDelete(_Ty *_Ptr)
    {   // delete from the debug CRT heap even if operator delete exists
    if (_Ptr != 0)
        {   // worth deleting
        _Ptr->~_Ty();
        // delete as _NORMAL_BLOCK, not _CRT_BLOCK, since we might have
        // facets allocated by normal new.
        free(_Ptr); // **ACCESS VIOLATION**
        }
    }

堆栈跟踪:

>   msvcp100d.dll!std::_DebugHeapDelete<void>(void * _Ptr)  Line 62 + 0xa bytes C++
    msvcp100d.dll!std::numpunct<char>::_Tidy()  Line 190 + 0xc bytes    C++
    msvcp100d.dll!std::numpunct<char>::~numpunct<char>()  Line 122  C++
    msvcp100d.dll!std::numpunct<char>::`scalar deleting destructor'()  + 0x11 bytes C++
    msvcp100d.dll!std::_DebugHeapDelete<std::locale::facet>(std::locale::facet * _Ptr)  Line 62 C++
    msvcp100d.dll!std::_Fac_node::~_Fac_node()  Line 23 + 0x11 bytes    C++
    msvcp100d.dll!std::_Fac_node::`scalar deleting destructor'()  + 0x11 bytes  C++
    msvcp100d.dll!std::_DebugHeapDelete<std::_Fac_node>(std::_Fac_node * _Ptr)  Line 62 C++
    msvcp100d.dll!_Fac_tidy()  Line 41 + 0x9 bytes  C++
    msvcp100d.dll!std::_Fac_tidy_reg_t::~_Fac_tidy_reg_t()  Line 48 + 0xe bytes C++
    msvcp100d.dll!std::`dynamic atexit destructor for '_Fac_tidy_reg''()  + 0xf bytes   C++
    msvcp100d.dll!_CRT_INIT(void * hDllHandle, unsigned long dwReason, void * lpreserved)  Line 415 C
    msvcp100d.dll!__DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved)  Line 526 + 0x11 bytes  C
    msvcp100d.dll!_DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved)  Line 476 + 0x11 bytes   C

有人对可能导致这种情况的原因有任何想法吗?

我读了一些关于缓存方面的内容,不确定这是否相关?

4

4 回答 4

4

如果您覆盖运算符 new 并使用您可能会遇到与我相同的原因。代码可能像

#include "yournew" //override new declare .. 
#include "fstream" 
std::fstream f
f.open(...)

因为 iostream 是模板,所以 _Fac_node 的 new 使用您的 operator new。但是退出时,你的内存池可能会在_Fac_tidy之前退出,然后当~_Fac_tidy()运行时,程序崩溃了。

于 2011-07-13T05:02:20.067 回答
2

内存损坏错误可以(显然)导致这种(和许多其他类型的)失败。

您是否尝试过使用 valgrind (memcheck) 或 Rational Purify 来解决这个问题?它可能会报告问题(如果这是您第一次对代码库进行此类检查,则可能隐藏在大量其他信息中。您仍然希望设计一个最小的“主要”实现来展示行为在内存和边界检查器下运行

0.02 美元

PS。以防万一,通常会出现内存损坏错误

  • 通过取消引用过时的指针(在释放/删除之后)
  • 通过写入超出分配缓冲区的末尾
  • 通过释放/删除以前的指针(主要是不良所有权跟踪的症状)
于 2011-04-05T23:05:40.880 回答
1

我相信您遇到了与我在 MSVC10 运行时相同的错误。据我了解,这是由于运行时在卸载 DLL 时删除了全局方面,然后在进程结束时再次删除它。如果您静态链接所有内容,则不应该发生。它也不会在 MSVC9 中发生,无论是静态链接还是共享链接。

于 2011-10-06T15:34:59.417 回答
1

第一个被接受的响应是正确的,但它并没有准确地显示原因以及修复它的方法。根据调用堆栈中列出的部分,我遇到了与 VC++8 (MS VS 2005) 相同的问题,但在不同的情况下:我的 CLR DLL 在代码的同一点导致 AV。

从列出的调用堆栈中可以看出,<xdebug>通常编译成 msvc*.dll 的代码被调用,但此时_Ptr已经有错误的值。因此,有一些代码要么已经释放了这个指针下的对象,要么设置了一个退出钩子来释放未初始化的对象。

如果_STATIC_CPPLIB已定义,则<xdebug>代码可以编译到加载到应用程序进程中的其他模块中。然后,这些模块的一个退出过程可以在 msvcp100d.dll 中的另一个退出过程之前被调用,因此可以正常释放 facet 对象。就我而言,_STATIC_CPPLIB定义后,两个模块(exe 和 clr dll)都已编译。

VC++8,9的解决方案

检查“命令行”部分中的最终编译器选项是否存在/D "_STATIC_CPPLIB". 取消定义_STATIC_CPPLIB和重新编译受影响的模块会在程序终止时修复 AV。

注意事项_STATIC_CPPLIB

对于VC++9_STATIC_CPPLIB,在 MSDN,有说明

不支持_STATIC_CPPLIB预处理器定义和 /clror编译器选项的组合。/clr:pure

并且没有提及_STATIC_CPPLIB更高的 VS 版本。对于更高的 VS 版本,尤其是 VS 10,我认为依赖的代码_STATIC_CPPLIB仍然存在。在 TS 的情况下,如果_STATIC_CPPLIB在任何包含 TU<string>或其他头文件的编译器选项中仍然使用 ,则<locale>这种不正确的组合可能会导致 AV.

于 2015-12-13T07:12:22.510 回答