2
votes

I don't even know where to start... Visual Studio keeps giving me a heap corruption error when I close my program. The position it breaks at varies. During the 40+ hours I have spent changing my code (removing smart pointers, removing implementation hiding, re-adding smart pointers, making every class non copyable, making destructors private, etc), 95% of the time when I looked at the call stack it had to do with boost::shared_ptr and std::shared_ptr(I switched between them to see if it'd help), about 75% of the time it had to do with the class CLevel being deleted by the shared_ptr.

After I made destructors private and created a function to delete them I thought I narrowed it down to me calling delete on a pointer to CLevel. like 50% of the time it was right after the call it gave me the error. I went into CLevel and and watched each variable to make sure they were deleted fine, and they were, the code went down into the base class and exited, it was on that exit the heap error popped up. But I couldn't figure out what was wrong, plus, it didn't always give and error there. Sometimes it threw the error after and I also believe before. Which makes it REAL hard to find the issue, especially since it happened in other classes (I think just CEntity or CEntityManager).

I had thought it HAD to be Boost doing something odd, because after removing smart pointers from within the class implementations and instead, when I requested a new instance of a class (CLevel and CEntity to be specific), the program gave the error after Application.run() exited (The smart pointers are inside run). the callstack showed the error happened just after or a little bit after "scalar deleting destructor".

A lot of the times the break was inside free.c. As of this moment it's at realloc.c. line 85. This error is like a month hold, I got so fed up of trying to fix it I decided to not delete any classes upon program exit, but I really don't want to go about it that way, what if I want things done later that happen on exit? A few minutes ago, the error happened twice on exit. One of them seemed to have to do with a smart pointer to ALLEGRO_EVENT_QUEUE and ALLEGRO_TIMER, I made them regular pointers and manually deleted them and the second one went away.

Right now, this is the call stack:

ntdll.dll!771b0474() [Frames below may be incorrect and/or missing, no symbols loaded for 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) Line 85 + 0x17 bytes C msvcr100d.dll!realloc_help(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, unsigned int nNewSize) Line 60 + 0x13 bytes C++ allegro-5.0.4-monolith-md-debug.dll!636d78c0()
allegro-5.0.4-monolith-md-debug.dll!636e0474()
allegro-5.0.4-monolith-md-debug.dll!636d11fe()
allegro-5.0.4-monolith-md-debug.dll!636d0905()
allegro-5.0.4-monolith-md-debug.dll!636d0703() Project Nairim.exe!Application::~Application() Line 104 + 0xf bytes C++ Project Nairim.exe!Application::`scalar deleting destructor'() + 0x2b bytes C++ Project Nairim.exe!main() Line 8 + 0x2b bytes C++ Project Nairim.exe!__tmainCRTStartup() Line 555 + 0x19 bytes C Project Nairim.exe!mainCRTStartup() Line 371 C kernel32.dll!750f339a() ntdll.dll!77119ed2()
ntdll.dll!77119ea5()

This is the code that I thought was the issue when it came to the deleter function(Note: This function never existed when this first started appearing a month ago.)

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;
}

There are others like it.

This is my full code(It's a lot): https://github.com/NaturalDre/Nairim

I'm a self-taught programmer so if the code looks atrocious or badly structured I apologize.

It would be great if someone pointed me toward the issue. This kind of stuff discourages me. I like computers 'cause everything is fixed, not variable (if you do this, this will happen even if it's not what you expect). This bug jumps around and stuff like that drives me crazy. And no relevant data in the program gets modified. CLevel just reads a file, creates a map, and then draws it when necessary.

Also, remember I was rapidly changing a lot of stuff so some things might seem odd or not implemented fully yet.

3
Wow, that's really long question..Kiril Kirov
if you corrupt the heap, it's natural that you catch the problem at a random place. you might want to read my answer to a similar question: stackoverflow.com/questions/6557779/…Karoly Horvath
You are looking in the wrong place for the reason the canary died. The methane leak occurred much earlier, in another corner of the mine. Use the <crtdbg.h> header, msdn.microsoft.com/en-us/library/974tc9t1.aspxHans Passant
Can you try to narrow it down and come to the point directly? The question is too big :)Arunmu
make sure to set EVERY pointer you use in code to NULL or 0 after deleting it - that will save you from random errors and eventualy you'll easily backtrace to position where you try to dereference null pointer. Also do not delete shared pointers! they handle themselves on their own and you're using them for that reason, otherwise you would just use simple pointers and experience the problems you experience now..Raven

3 Answers

2
votes

Time to get busy with WinDbg, GFlags, and AppVerifier. These are tools that can crash a program earlier and allow you to break into a debugger to see where the memory corruption has occurred.

0
votes

I can confirm that AppVerifier is a great way to go. I've used it myself for some nasty bugs and it works nicely. Haven't tried WinDbg and GFlags, but App Verifier and Visual studio definitively worked to show where the issues were happening.

0
votes

AppVerifier is not support after VS 2008. You can get some alternatives like C++ Memory Validator. It's a very helpful and powerful tool.