Heap corruption - "Free Heap block 61af0f0 modified at 61af194 after it was freed" C++

15,003

Solution 1

So from what I know, the error I'm getting is caused by accessing (deleting again) block of memory which was already freed.

Unless there's something you know and are not telling us, the above can well be a red herring. The error could also mean that you're modifying memory through a dangling pointer, or due to a buffer overrun.

If you ever make copies of pointers (either explicitly, or by failing to define copy constructors/assignment operators), setting m_pVar = nullptr upon deletion will provide no gurantees against double deletes, let alone other types of memory errors.

If you can't find the problem by examining the code, your best bet might be a tool like Valgrind or Purify.

Solution 2

Crash during malloc is a sure sign of memory corruption and it may or may not be due to double delete. Corruption happened in some different part of your code and unfortunately the effect ripples out in your failing code which is definitely innocent. If possible, try to port your application in a system where you can run valgrind

Share:
15,003
Piotr Chojnacki
Author by

Piotr Chojnacki

Updated on July 02, 2022

Comments

  • Piotr Chojnacki
    Piotr Chojnacki almost 2 years

    In my application I'm getting this error:

    HEAP[App.exe]: HEAP: Free Heap block 61af0f0 modified at 61af194 after it was freed
    

    Here is a call stack:

        ntdll.dll!_RtlpBreakPointHeap@4()   Unknown
        ntdll.dll!@RtlpAllocateHeap@24()    Unknown
        ntdll.dll!_RtlAllocateHeap@12() Unknown
        ntdll.dll!_RtlDebugAllocateHeap@12()    Unknown
        ntdll.dll!@RtlpAllocateHeap@24()    Unknown
        ntdll.dll!_RtlAllocateHeap@12() Unknown
    >   msvcr110d.dll!_heap_alloc_base(unsigned int size) Line 57   C
        msvcr110d.dll!_heap_alloc_dbg_impl(unsigned int nSize, int nBlockUse, const char * szFileName, int nLine, int * errno_tmp) Line 431 C++
        msvcr110d.dll!_nh_malloc_dbg_impl(unsigned int nSize, int nhFlag, int nBlockUse, const char * szFileName, int nLine, int * errno_tmp) Line 239  C++
        msvcr110d.dll!_nh_malloc_dbg(unsigned int nSize, int nhFlag, int nBlockUse, const char * szFileName, int nLine) Line 302    C++
        msvcr110d.dll!malloc(unsigned int nSize) Line 56    C++
        msvcr110d.dll!operator new(unsigned int size) Line 59   C++
        App.exe!std::_Allocate<char>(unsigned int _Count, char * __formal) Line 28  C++
        App.exe!std::allocator<char>::allocate(unsigned int _Count) Line 591    C++
        App.exe!std::basic_stringbuf<char,std::char_traits<char>,std::allocator<char> >::overflow(int _Meta) Line 152   C++
        msvcp110d.dll!std::basic_streambuf<char,std::char_traits<char> >::sputc(char _Ch) Line 196  C++
        msvcp110d.dll!std::ostreambuf_iterator<char,std::char_traits<char> >::operator=(char _Right) Line 634   C++
        msvcp110d.dll!std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::_Put(std::ostreambuf_iterator<char,std::char_traits<char> > _Dest, const char * _Ptr, unsigned int _Count) Line 1553  C++
        msvcp110d.dll!std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::_Iput(std::ostreambuf_iterator<char,std::char_traits<char> > _Dest, std::ios_base & _Iosbase, char _Fill, char * _Buf, unsigned int _Count) Line 1544 C++
        msvcp110d.dll!std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char,std::char_traits<char> > _Dest, std::ios_base & _Iosbase, char _Fill, long _Val) Line 1216   C++
        msvcp110d.dll!std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::put(std::ostreambuf_iterator<char,std::char_traits<char> > _Dest, std::ios_base & _Iosbase, char _Fill, long _Val) Line 1137  C++
        msvcp110d.dll!std::basic_ostream<char,std::char_traits<char> >::operator<<(int _Val) Line 311   C++
        App.exe!TUtil::intToString(int val) Line 43 C++
        App.exe!TFontManager::getFont(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & filename, int size) Line 15  C++
        App.exe!TButton::draw() Line 55 C++
        App.exe!TWindow::draw() Line 203    C++
        App.exe!TGUIManager::drawObjects() Line 49  C++
        App.exe!TGameAppLayer::gameCycle() Line 456 C++
        App.exe!TGameAppLayer::mainLoop() Line 520  C++
        App.exe!wWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) Line 36   C++
        App.exe!__tmainCRTStartup() Line 528    C
        App.exe!wWinMainCRTStartup() Line 377   C
        kernel32.dll!@BaseThreadInitThunk@12()  Unknown
        ntdll.dll!___RtlUserThreadStart@8() Unknown
        ntdll.dll!__RtlUserThreadStart@8()  Unknown
    

    So from what I know, the error I'm getting is caused by accessing (deleting again) block of memory which was already freed. It's already a third day of trying finding out what exactly is wrong with my code. During this time, I found some small memory leaks which I already fixed, and now Visual Leak Detector tells me it doesn't detect any leak.

    Yet the problem with heap corruption remains.

    In each place of my code in a place where "delete" operator is being used, I check first if a pointer isn't nullptr. If not, I set it to nullptr:

    if(m_pVar != nullptr)
    {
        delete m_pVar;
        m_pVar = nullptr;
    }
    

    So it seems like there shouldn't be a problem with freeing same block of memory more than once.

    I was trying to figure something out from this call stack, but that's place in which I'd like to ask you for a help. In a call stack it seems like a problem is with string allocation, but what exactly may this mean? The last MY function that is being called is string TUtil::intToString(int val) Line 43, so it may be easier if I show you a body of that function:

    std::string TUtil::intToString(int val)
    {
        std::ostringstream s;
        s << val;                 // Here's line 43
        return s.str();
    }
    

    Sometimes call stack is different, so string TUtil::intToString(int val) function doesn't even exist in it, but it ALWAYS has something to do with strings allocations.

    I hope it's clear what I just said. If you need more information, please tell me and I'll provide it in edit to this question.

  • Piotr Chojnacki
    Piotr Chojnacki over 11 years
    Thank you for the answer NPE! Sorry for a bit late reply, but I was still trying to find a problem according to hints you all gave me and I finally found it thanks to "Application Verifier" and "Debug Diagnostics Tool" programs. It appears that I've been using pointer to block of memory which was already freed.
  • Piotr Chojnacki
    Piotr Chojnacki over 11 years
    Thank you Abhijit for the answer. The problem was using a pointer to block of memory which was already freed.