2011-09-10 84 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。這是一個非常有用和強大的工具。