_DebugHeap删除终止时的访问冲突

时间:2011-04-05 22:30:59

标签: c++ access-violation termination

我在主要结束时遇到了一个奇怪的访问违规行为,其原因是我遇到了一些困难。

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

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 个答案:

答案 0 :(得分:4)

如果您覆盖操作员new并使用,您可能会遇到与我相同的原因。 代码可能就像

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

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

答案 1 :(得分:2)

内存损坏错误(显然)会导致此(以及许多其他类型)失败。

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

$ 0.02

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

  • 通过解除引用过时指针(在释放/删除之后)
  • 通过写入超出分配缓冲区的结尾
  • 通过释放/删除以前的指针(主要是不良所有权跟踪的症状)

答案 2 :(得分:1)

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

答案 3 :(得分:1)

第一个被接受的回答是正确的,但它没有准确地说明理由,因此也没有说明修复它的方法。根据调用堆栈列出的部分,我遇到了与VC ++ 8(MS VS 2005)相同的问题,但在不同的情况下:我的CLR DLL导致AV在代码的同一点。

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

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

VC ++ 8,9的解决方案

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

_STATIC_CPPLIB注意

对于VC++9 _STATIC_CPPLIB,在MSDN上,有一条注释

  

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

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