堆腐败

时间:2011-09-10 18:18:14

标签: c++ memory smart-pointers dealloc heap-corruption

我甚至不知道从哪里开始......当我关闭程序时,Visual Studio一直给我一个堆损坏错误。它破坏的位置各不相同。在40多个小时内,我花了一些时间来改变我的代码(删除智能指针,删除实现隐藏,重新添加智能指针,使每个类不可复制,使析构函数成为私有等),95%的时间我查看了调用堆栈它与boost :: shared_ptr和std :: shared_ptr有关(我在它们之间切换以查看它是否有帮助),大约75%的时间与shared_ptr删除类CLevel有关。

在我将析构函数设为私有并创建了一个删除它们的函数后,我想我把它缩小到我在指向CLevel的指针上调用delete。就像50%的时间它在电话会议后它给了我错误。我进入了CLevel并观察了每个变量,以确保它们被删除得很好,而且它们是,代码进入基类并退出,它在那个出口处弹出堆错误。但我无法弄清楚出了什么问题,而且,它并没有总是给出错误。有时它会抛出错误,我之前也相信。这使得很难找到问题,特别是因为它发生在其他类中(我认为只是CEntity或CEntityManager)。

我曾经认为它是Boost做一些奇怪的事情,因为在从类实现中删除智能指针之后,当我请求一个类的新实例(CLevel和CEntity是特定的)时,程序给了退出Application.run()后出错(智能指针在运行中)。 callstack显示错误发生在“标量删除析构函数”之后或之后。

很多时候休息都在free.c.截至目前,它处于realloc.c。第85行。这个错误就像一个月举行,我厌倦了试图解决它我决定不退出程序退出任何类,但我真的不想这样做,如果我想要以后在退出时发生的事情?几分钟前,错误在退出时发生了两次。其中一个似乎与指向ALLEGRO_EVENT_QUEUE和ALLEGRO_TIMER的智能指针有关,我将它们作为常规指针并手动删除它们,第二个指针消失了。

现在,这是调用堆栈:

  

ntdll.dll!771b0474()[下面的框架可能不正确和/或   缺少,没有为ntdll.dll加载的符号] ntdll.dll!7716afc3()
    ntdll.dll!7716b0ad()ntdll.dll!77195665()
    ntdll.dll!77172990()ntdll.dll!77195665()
    ntdll.dll!77172990()ntdll.dll!77121fec()

     
    

msvcr100d.dll!_realloc_base(void * pBlock,unsigned int newsize)     第85行+ 0x17字节C msvcr100d.dll!realloc_help(void * pUserData,     unsigned int * pnNewSize,int nBlockUse,const char * szFileName,int     nLine,int fRealloc)行832 + 0x10字节C ++       msvcr100d.dll!_realloc_dbg(void * pUserData,unsigned int nNewSize,     int nBlockUse,const char * szFileName,int nLine)Line 1040 + 0x1b     bytes C ++ msvcr100d.dll!realloc(void * pUserData,unsigned int     nNewSize)第60行+ 0x13字节C ++       快板-5.0.4-整体-MD-debug.dll!636d78c0()
      快板-5.0.4-整体-MD-debug.dll!636e0474()
      快板-5.0.4-整体-MD-debug.dll!636d11fe()
      快板-5.0.4-整体-MD-debug.dll!636d0905()
      allegro-5.0.4-monolith-md-debug.dll!636d0703()项目     Nairim.exe!Application :: ~Application()第104行+ 0xf字节C ++       Project Nairim.exe!Application ::`标量删除析构函数'()+     0x2b字节C ++ Project Nairim.exe!main()第8行+ 0x2b字节C ++       Project Nairim.exe!__ tmainCRTStartup()第555行+ 0x19字节C.       Project Nairim.exe!mainCRTStartup()第371 C行       kernel32.dll!750f339a()ntdll.dll!77119ed2()
      NTDLL.DLL!77119ea5()

  

这是我认为在删除函数时出现问题的代码(注意:这个函数在一个月前首次出现时从未存在过。)

void PN::CLevelManager::destroyLevel(const pLevel _ptr)
{
    assert(LevelMgr.get() != NULL);
    std::cout << std::endl << LevelMgr.get();
    auto iter = std::find(LevelMgr->m_levelList.begin(), LevelMgr->m_levelList.end(), _ptr);
    if (iter != LevelMgr->m_levelList.end())
        LevelMgr->m_levelList.erase(iter);
    delete _ptr;
}

还有其他人喜欢它。

这是我的完整代码(很多):https://github.com/NaturalDre/Nairim

我是一名自学成才的程序员,所以如果代码看起来很糟糕或结构糟糕,我道歉。

如果有人指出我这个问题会很棒。这种东西让我气馁。我喜欢计算机,因为一切都是固定的,而不是可变的(如果这样做,即使它不是你所期望的,也会发生这种情况)。这个bug跳了起来,这样的东西让我发疯。并且程序中的相关数据不会被修改。 CLevel只读取一个文件,创建一个地图,然后在必要时绘制它。

另外,请记住我正在迅速改变很多东西,所以有些东西可能看起来很奇怪或者还没有完全实现。

3 个答案:

答案 0 :(得分:2)

忙于WinDbgGFlags, and AppVerifier的时间。这些工具可以使程序更早崩溃,并允许您进入调试器以查看内存损坏发生的位置。

答案 1 :(得分:0)

我可以确认AppVerifier是一个很好的方法。我自己用它来处理一些令人讨厌的bug,它运行得很好。没有尝试过WinDbg和GFlags,但App Verifier和Visual studio最终确定了问题发生的位置。

答案 2 :(得分:0)

VS 2008之后不支持AppVerifier。您可以获得一些替代方案,如C ++ Memory Validator。这是一个非常有用和强大的工具。