none
Buffer overwrite, HEAP CORRUPTION DETECTED

    Question

  • Hi,

    I wouldn't be asking this but this problem sometimes occurs directly after the line..

    int main(int argc, char **argv[])
    {
    PWCHAR var = (PWCHAR) malloc ((sizeof("some\\string") * sizeof(WCHAR)) + sizeof(WCHAR));

    "HEAP CORRUPTION DETECTED after normal block (#60) at 0x00000000xxxxxxxx."
    "CRT detected the application wrote to memory after the end of the heap buffer."

    The problem never always occurs the same line and sometimes - usually - when I run through the code step by step (F10) lines are executed but the arrow jumps past lines unless I set a specific breakpoint on the line.

    Previously another error that has occurred has been a write to invalid memory. (Error - 0x00000005, ACCESS_DENIED)

    The code seems fine when compiled as 32bit (no problems have ever occurred.) but the problems certainly occur when compiled as 64bit.

    I would like to know if it is possible that code that has been compiled has somehow been corrupted and is causing this error. I ask this only because I have had the HEAP CORRUPTION error occurred directly after the first run statement.

    Thankyou, I really need the help.

    Wednesday, May 09, 2012 3:29 PM

Answers

  • Heap corruptions are caused by writing too much to a memory buffer, and that is never a compiler error.

    Heap corruptions only manifest the next time you try to do something with the heap itself, like allocate more memory or free a block of memory, so it wouldn't occur after you overwrite the end of the buffer.

    As for the debugger jumping past lines, is your configuration set to release? When it optimises code, it may remove lines completely. The debugger will just not go onto those lines. If you want the best possible debug experience, make sure it is set to the debug configuration.

    For a simple way of causing a heap corruption, try the following code. It will always trigger on the free line.

    int wmain()
    {
    	wchar_t *mystr = (wchar_t*)malloc(24);
    
    	wcscpy(mystr, L"a longer string");
    
    	free(mystr); //will break here
    	mystr = nullptr;
    
    	return 0;
    }

    This causes a heap corruption because obviously the buffer can only store 12 characters (including the null terminator) and you copy more than that to the buffer. The obvious way to fix this is to increase the size of the buffer.

    If you want more help though, provide code. Either your actual code or a small sample that reproduces the same issue.


    This is a signature

    Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    Do you want Visual Studio 11 Express to be freely installable on Windows 7 and able to write regular C++ applications? Please vote for this.

    • Marked as answer by Helen Zhao Friday, May 11, 2012 5:38 AM
    • Unmarked as answer by Helen Zhao Friday, May 11, 2012 5:39 AM
    • Marked as answer by Helen Zhao Thursday, May 17, 2012 3:25 AM
    Wednesday, May 09, 2012 3:44 PM
  • HEAP CORRUPTION DETECTED is usually caused by using bad pointers or indexes in some previously executed code.  I.e., not by the line of code that produces the message. Your malloc call just gives the heap checker an opportunity to check for heap damage caused by previous operations.

    If you have constructors of global objects they run before main(). So that would be a good place to look for trouble.

    • Marked as answer by Helen Zhao Friday, May 11, 2012 5:38 AM
    • Unmarked as answer by Helen Zhao Friday, May 11, 2012 5:39 AM
    • Marked as answer by Helen Zhao Thursday, May 17, 2012 3:25 AM
    Wednesday, May 09, 2012 3:43 PM
  • Hi,

    I wouldn't be asking this but this problem sometimes occurs directly after the line..

    int main(int argc, char **argv[])

    It is probably not related to your problem but this is not a legal definition for main. Your second parameter can be char **argv or char *argv[] but not what you have posted.

    {
    PWCHAR var = (PWCHAR) malloc ((sizeof("some\\string") * sizeof(WCHAR)) + sizeof(WCHAR));

    "HEAP CORRUPTION DETECTED after normal block (#60) at 0x00000000xxxxxxxx."
    "CRT detected the application wrote to memory after the end of the heap buffer."

    <snip>

    Previously another error that has occurred has been a write to invalid memory. (Error - 0x00000005, ACCESS_DENIED)

    This inidcates you already have used a bad pointer.

    You need to show your actual code since it is obviouls the call to malloc is not that early.

    • Marked as answer by Helen Zhao Friday, May 11, 2012 5:38 AM
    • Unmarked as answer by Helen Zhao Friday, May 11, 2012 5:39 AM
    • Marked as answer by Helen Zhao Thursday, May 17, 2012 3:25 AM
    Wednesday, May 09, 2012 5:14 PM
  • You're not helping yourself by mixing narrow string literals in your sizeof() expressions with wide string literals in your wcscpy() calls.  However, it doesn't seem to be the underlying problem - unless your WCHAR is not a two byte type like wchar_t.

    You can safely replace

    PWCHAR var = (PWCHAR) malloc ((sizeof("some\\string") * sizeof(WCHAR)) + sizeof(WCHAR));
    wcscpy(var, L"some\\string");

    with the equivalent

    PWCHAR var = (PWCHAR) _wcsdup(L"some\\string");

    Of course, you should always check for a NULL pointer from malloc() and _wcsdup().


    Answering policy: see profile.

    • Marked as answer by Helen Zhao Friday, May 11, 2012 5:38 AM
    • Unmarked as answer by Helen Zhao Friday, May 11, 2012 5:39 AM
    • Marked as answer by Helen Zhao Thursday, May 17, 2012 3:25 AM
    Wednesday, May 09, 2012 5:25 PM
  • I suggest you to use the _vsnwprintf  function, where you specify the maximum number of characters to write. Also check if you use the “( )” parentheses correctly in malloc, and your msg is always compatible with arguments.

    • Marked as answer by Helen Zhao Friday, May 11, 2012 5:39 AM
    • Unmarked as answer by Helen Zhao Friday, May 11, 2012 5:39 AM
    • Marked as answer by Helen Zhao Thursday, May 17, 2012 3:25 AM
    Wednesday, May 09, 2012 5:54 PM

All replies

  • " occurs directly after the line.."

    And what's after that line? that malloc by itself can't possible cause heap corruption, there must be some other code that overwrites some memory.

    Wednesday, May 09, 2012 3:35 PM
  • HEAP CORRUPTION DETECTED is usually caused by using bad pointers or indexes in some previously executed code.  I.e., not by the line of code that produces the message. Your malloc call just gives the heap checker an opportunity to check for heap damage caused by previous operations.

    If you have constructors of global objects they run before main(). So that would be a good place to look for trouble.

    • Marked as answer by Helen Zhao Friday, May 11, 2012 5:38 AM
    • Unmarked as answer by Helen Zhao Friday, May 11, 2012 5:39 AM
    • Marked as answer by Helen Zhao Thursday, May 17, 2012 3:25 AM
    Wednesday, May 09, 2012 3:43 PM
  • Heap corruptions are caused by writing too much to a memory buffer, and that is never a compiler error.

    Heap corruptions only manifest the next time you try to do something with the heap itself, like allocate more memory or free a block of memory, so it wouldn't occur after you overwrite the end of the buffer.

    As for the debugger jumping past lines, is your configuration set to release? When it optimises code, it may remove lines completely. The debugger will just not go onto those lines. If you want the best possible debug experience, make sure it is set to the debug configuration.

    For a simple way of causing a heap corruption, try the following code. It will always trigger on the free line.

    int wmain()
    {
    	wchar_t *mystr = (wchar_t*)malloc(24);
    
    	wcscpy(mystr, L"a longer string");
    
    	free(mystr); //will break here
    	mystr = nullptr;
    
    	return 0;
    }

    This causes a heap corruption because obviously the buffer can only store 12 characters (including the null terminator) and you copy more than that to the buffer. The obvious way to fix this is to increase the size of the buffer.

    If you want more help though, provide code. Either your actual code or a small sample that reproduces the same issue.


    This is a signature

    Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    Do you want Visual Studio 11 Express to be freely installable on Windows 7 and able to write regular C++ applications? Please vote for this.

    • Marked as answer by Helen Zhao Friday, May 11, 2012 5:38 AM
    • Unmarked as answer by Helen Zhao Friday, May 11, 2012 5:39 AM
    • Marked as answer by Helen Zhao Thursday, May 17, 2012 3:25 AM
    Wednesday, May 09, 2012 3:44 PM
  • With regards to the missing lines.

    I set a breakpoint on:
    PWCHAR var = (PWCHAR) malloc ((sizeof("some\\string") * sizeof(WCHAR)) + sizeof(WCHAR));
    Press F10.
    and the next line the arrow appears is: (I definately pressed F10 and all inbetween lines have been executed.)
    t1 = function(vab, pointertoafunc);

    It is set to custom but copied from Debug.

    int main(int argc, char **argv[])
    {
    (breakpoint) PWCHAR var = (PWCHAR) malloc ((sizeof("some\\string") * sizeof(WCHAR)) + sizeof(WCHAR));
     PWCHAR vab = (PWCHAR) malloc ((sizeof("asome\\string2") * sizeof(WCHAR)) + sizeof(WCHAR));

     unsigned int t1, t2, t3;

     wcscpy(var, L"some\\string");
     wcscpy(vab, L"asome\\string2");

    (breakpoint) t1 = function(vab, pointertoafunc);

    I will look again at where the memory is being overwritten.

    Wednesday, May 09, 2012 3:59 PM
  • Hi,

    I wouldn't be asking this but this problem sometimes occurs directly after the line..

    int main(int argc, char **argv[])

    It is probably not related to your problem but this is not a legal definition for main. Your second parameter can be char **argv or char *argv[] but not what you have posted.

    {
    PWCHAR var = (PWCHAR) malloc ((sizeof("some\\string") * sizeof(WCHAR)) + sizeof(WCHAR));

    "HEAP CORRUPTION DETECTED after normal block (#60) at 0x00000000xxxxxxxx."
    "CRT detected the application wrote to memory after the end of the heap buffer."

    <snip>

    Previously another error that has occurred has been a write to invalid memory. (Error - 0x00000005, ACCESS_DENIED)

    This inidcates you already have used a bad pointer.

    You need to show your actual code since it is obviouls the call to malloc is not that early.

    • Marked as answer by Helen Zhao Friday, May 11, 2012 5:38 AM
    • Unmarked as answer by Helen Zhao Friday, May 11, 2012 5:39 AM
    • Marked as answer by Helen Zhao Thursday, May 17, 2012 3:25 AM
    Wednesday, May 09, 2012 5:14 PM
  • You're not helping yourself by mixing narrow string literals in your sizeof() expressions with wide string literals in your wcscpy() calls.  However, it doesn't seem to be the underlying problem - unless your WCHAR is not a two byte type like wchar_t.

    You can safely replace

    PWCHAR var = (PWCHAR) malloc ((sizeof("some\\string") * sizeof(WCHAR)) + sizeof(WCHAR));
    wcscpy(var, L"some\\string");

    with the equivalent

    PWCHAR var = (PWCHAR) _wcsdup(L"some\\string");

    Of course, you should always check for a NULL pointer from malloc() and _wcsdup().


    Answering policy: see profile.

    • Marked as answer by Helen Zhao Friday, May 11, 2012 5:38 AM
    • Unmarked as answer by Helen Zhao Friday, May 11, 2012 5:39 AM
    • Marked as answer by Helen Zhao Thursday, May 17, 2012 3:25 AM
    Wednesday, May 09, 2012 5:25 PM
  • Hi,

    That is my first line. I haven't changed anything, however the skipping of lines - which appears to have stopped but I do not understand why - could mean that other lines were executed not only the malloc. I am still confused as to why that has happened. Anyhow,

    I have identified the problem to this function. Is there any problem with this code if compiled for 64bit?

    unsigned int custom(func myfunc, unsigned long size, const PWCHAR msg, ...)
    {
     PWCHAR b;
     va_list args;

     b = (PWCHAR) malloc (size * sizeof(WCHAR)) + sizeof(WCHAR));
     if(!b) return 0;
     va_start(args, msg);

     vswprintf(b, msg, args);
     va_end(args);

     myfunc(b);

     if(b) free(b);

     return 1;
    }

    Thankyou.

    Wednesday, May 09, 2012 5:39 PM
  • I suggest you to use the _vsnwprintf  function, where you specify the maximum number of characters to write. Also check if you use the “( )” parentheses correctly in malloc, and your msg is always compatible with arguments.

    • Marked as answer by Helen Zhao Friday, May 11, 2012 5:39 AM
    • Unmarked as answer by Helen Zhao Friday, May 11, 2012 5:39 AM
    • Marked as answer by Helen Zhao Thursday, May 17, 2012 3:25 AM
    Wednesday, May 09, 2012 5:54 PM
  • Your latest code sample will not compile due to mismatched parentheses in the malloc line.
    Wednesday, May 09, 2012 6:21 PM
  • I had to change a few of the variable names and I must have removed a ( by mistake. Thankyou.
    Wednesday, May 09, 2012 6:36 PM
  • I've made the changes you've suggested but I still get this error in that function.

    On free(buf); or va_end();

    Managed Debugging Assistant 'FatalExecutionEngineError' has detected a problem in 'path\file.exe'.
    Additional Information: The runtime has encountered a fatal error. The address of the error was at 0xeec91380, on thread 0xc48. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.

    Wednesday, May 09, 2012 6:38 PM
  • "HEAP CORRUPTION DETECTED after normal block (#60) at 0x00000000xxxxxxxx."

    It might be helpful to know that you can set a breakpoint on the actual allocation call of the block - in this case, block number 60 ("(#60)" above).  See the Setting Breakpoints on a Memory Allocation Number section in Finding Memory Leaks Using the CRT Library

    Answering policy: see profile.

    • Proposed as answer by Helen Zhao Friday, May 11, 2012 5:39 AM
    • Unproposed as answer by Helen Zhao Friday, May 11, 2012 5:39 AM
    Wednesday, May 09, 2012 9:18 PM
  • unsigned int custom(func myfunc, unsigned long size, const PWCHAR msg, ...)
    {
     PWCHAR b;
     va_list args;

     b = (PWCHAR) malloc (size * sizeof(WCHAR)) + sizeof(WCHAR));
     if(!b) return 0;

    <snip>

     if(b) free(b);

     return 1;
    }


    There is no need to test b.  NULL is a valid value to pass to free.  Besides, you already tested b and know that it cannot be NULL.
    Wednesday, May 09, 2012 10:30 PM