2011-09-10 86 views
2

我什至不知道从哪里开始......当我关闭我的程序时,Visual Studio不断给我一个堆腐败错误。它所处的位置各不相同。在40多个小时内,我花了不少时间更换代码(删除智能指针,删除实现隐藏,重新添加智能指针,使每个类都不可复制,使析构函数保密等等),95%的时间在我看到呼叫时它必须与boost :: shared_ptr和std :: shared_ptr(我在它们之间切换以查看它是否会有所帮助)进行堆栈,约75%的时间与使用shared_ptr删除CLevel类有关。堆腐败

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

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

很多时间休息是在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.dl (void * pUserData, unsigned int * pnNewSize,int nBlockUse,const char * szFileName,int nLine,int fRealloc)无符号整数* Line 832 + 0x10 bytes 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,无符号整型 nNewSize)线60 + 0×13字节C++ 快板-5.0.4-整料-MD-debug.dll!636d78c0()
快板-5.0.4-整料-MD-debug.dll!636e0474()
快板-5.0.4-整体-MD-debug.dll!636d11fe( )
allegro-5.0.4-monolith-md-debug.dll!636d0905()
allegro-5.0.4-monolith-md-debug.dll!636d0703()项目 奈及利亚。EXE应用程序::〜应用程序()行104 + 0xf字节C++ 项目Nairim.exe!应用程序::`标量删除析构函数'()+ 0x2b字节C++项目Nairim.exe!main()行8 + 0x2b字节C++ 项目Nairim.exe!__ tmainCRTStartup()线555个+ 0x19字节ç 项目Nairim.exe!mainCRTStartup()线371℃ 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只读取一个文件,创建一个映射,然后在需要时绘制它。另外,记住我正在迅速改变很多东西,所以有些东西可能看起来很奇怪,或者还没有完全实现。

+2

哇,这真的是个很长的问题.. –

+0

如果你损坏了堆,很自然你会在随机的地方发现问题。你可能想阅读我的答案类似的问题:http://stackoverflow.com/questions/6557779/memory-allocation-heap-corruption-in-stdstring-constructor/6557811#6557811 –

+4

您正在寻找错误的地方为金丝雀死去的原因。甲烷泄漏发生得早得多,在矿井的另一个角落。使用''标题,http://msdn.microsoft.com/en-us/library/974tc9t1.aspx –

回答

0

我可以证实AppVerifier是一个很好的选择。我自己使用它来处理一些令人讨厌的错误,它很好地工作。还没有尝试WinDbg和GFlags,但App Verifier和Visual Studio确切地工作以显示问题发生的位置。

0

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