VS2005 debug CRT does not report file/line info for heap corruption

Hi hyslopc!
I just ran a test of the VS 2005 beta 2 debug CRT library

_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_CHECK_EVERY_1024_DF | _CRTDBG_CHECK_CRT_DF);

char * Test = new char[3];

Test[3] = '\0'; // Cause memory corruption

delete Test;

This results in a dialog box being shown which says that a heap overwrite occured with allocation X at location Y.  No really useful information such as the filename/line number where the allocation occurred, or the number of bytes allocated.

If I jump into the debugger at that point, I see that the message was generated by line 1171 of dbgheap.c, and that it was generated from a _CrtMemBlockHeader structure which includes all of the useful info that I has hoped would be displayed.

So my question to the VC++ RTL guys is: you have the file/line info right there, why the heck don't you include it in the message

This is by design (and is almost the same behavior under all previous version of VC).

"malloc" is a define; here the __LINE__ and __FILE__ macro works correctly.
"new" is a function, therefor the __LINE__ and __FILE__ macro does not give you the right values... (or always the same).

For this you need an 3rd Party leak-finder (currently I am redisigning my leakfinder at http://blog.kalmbachnet.de/ postid=13)
-- 
Greetings
 Jochen Kalmbach
 Microsoft MVP VC++

  My blog about Win32 and .NET
  http://blog.kalmbachnet.de/
  
PS: Please mark an answer as "answered" if it helped!!!


Answer this question

VS2005 debug CRT does not report file/line info for heap corruption

  • getrajnish

    Hi hyslopc!
    I think this is simply a miss on the part of the CRT.  If I change my code so that it doesn't delete the corrupt block, but just lets it sit there, then within 1024 allocations later, _CrtCheckMemory() gets called, and it *does* log the file/line info (on line 1607 of dbgrpt.c).  So the CRT behaves inconsistently depending on how the problem is detected.  I am going to report this to MS as a bug.
    In your example you do a unallowed  memory-overwrite!
    What info do you expect from the CRT in this situation

    The only think the CRT can do is to say "Hey!" It has no context info who has written to the gap-place!

    (Or maybe I misunderstand your question again...)
    -- 
    Greetings
     Jochen Kalmbach
     Microsoft MVP VC++
    
      My blog about Win32 and .NET
      http://blog.kalmbachnet.de/
      
    PS: Please mark an answer as "answered" if it helped!!!

  • emz chisnky

    That used to be true, but Microsoft added their own debug versions of new and delete at some point.  Do this after including <crtdbg.h>:

    #define new DEBUG_NEW
    #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)

    - and you will get file & line info for new as well as malloc and free.  Of course it only works with the debug CRT.  The only real downside to it is that you must undefine new before including any of the STL headers that use the placement new syntax.  This is pretty stupid, IMHO, since it would be so simple for the STL headers to handle this themselves (and yes I know they are outsourced to Dinkumware, but still).

    So the info is there, why doesn't the CRT utilize it

  • Krams

    Sorry you are right - the file/line info isn't shown in the messagebox by default, it's only displayed within the debugger's output window.  I was testing all this within an existing project which had another call I had forgotten about:

    _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_WNDW);

    If you add this, then it will display the file/line info in a messagebox, after you hit "Ignore" to the first one.


  • tnec

    Sorry, I don't understand your question.  I suggest you just compile a little code sample like I did.  You will see exactly the problem them.  If you delete the pointer, you get an error message with no file/line info (bad).  If instead you call _CrtCheckMemory(), or just wait until enough allocations have occured such that it gets called automatically, then you get an error message with file/line info (good).

    All MS has to do is copy the same logic they have in _CrtCheckMemory() into free_dbg_nolock().

  • thunderbird

    hyslopc@discussions.microsoft.com wrote:
    Sorry, I don't understand your question.  I suggest you just compile a little code sample like I did.  You will see exactly the problem them.  If you delete the pointer, you get an error message with no file/line info (bad).  If instead you call _CrtCheckMemory(), or just wait until enough allocations have occured such that it gets called automatically, then you get an error message with file/line info (good).

    All MS has to do is copy the same logic they have in _CrtCheckMemory() into free_dbg_nolock().
    I have the following example:
    #include <stdlib.h>
    #include <crtdbg.h>
    int main()
    {
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_CHECK_EVERY_1024_DF | _CRTDBG_CHECK_CRT_DF);
    char * Test = new char[3];
    Test[3] = '\0'; // Cause memory corruption
    delete Test;
    return 0;
    }


    This produces a window with the following content:
    "Debug Error .... Heap corruption error" (no line/file info).

    Now we remove the "delete Test" and repalce this with:

    for(int i=0; i<2000; i++)
    {
      char *c = (char*) malloc(10); free(c);
    }


    Now we get an error message like:
    "Debug assertion failed! _CrtCheckMemory" (with useless file/line info: dbgheap.c:358)


    You are correct in the fact, that there is an inconsistency between the two message-boxes.
    But: What is the different to the developer Both dialogs only tells them that there is a memory corruption... not more and not less... the provided line/file info is completly useless...
    -- 
    Greetings
     Jochen Kalmbach
     Microsoft MVP VC++
    
      My blog about Win32 and .NET
      http://blog.kalmbachnet.de/
      
    PS: Please mark an answer as "answered" if it helped!!!

  • lichh_2003

    Sorry... I misread your question (I thougt you are woundering why the "new" mem-leak-display fails"....)

    But where can you see some usefull infos in the "pHead" variable
    -- 
    Greetings
     Jochen Kalmbach
     Microsoft MVP VC++
    
      My blog about Win32 and .NET
      http://blog.kalmbachnet.de/
      
    PS: Please mark an answer as "answered" if it helped!!!

  • &amp;#42;Lysander&amp;#42;

    As I wrote earlier, and specified in the bug report (but unfortunately did not include in my initial post), you need to do this:

    #define new DEBUG_NEW
    #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)

    - after including crtdbg.h.  Then you get very useful file/line info.  Try it and you will see.

  • mediaman

    I think this is simply a miss on the part of the CRT.  If I change my code so that it doesn't delete the corrupt block, but just lets it sit there, then within 1024 allocations later, _CrtCheckMemory() gets called, and it *does* log the file/line info (on line 1607 of dbgrpt.c).  So the CRT behaves inconsistently depending on how the problem is detected.  I am going to report this to MS as a bug.
  • _aaa_

    Hi hyslopc! > #define new DEBUG_NEW > #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) > > - after including crtdbg.h. Then you get very useful file/line info. > Try it and you will see. Maybe I am too stupid... #include #include #define new DEBUG_NEW #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) int main() { _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_CHECK_EVERY_1024_DF | _CRTDBG_CHECK_CRT_DF); char * Test = new char[3]; Test[3] = '\0'; // Cause memory corruption //delete Test; for(int i=0; i<2000; i++) { char *c = (char*) malloc(10); free(c); } return 0; } => "Debug Assertion Failed: (useless line/file-info (dbghep.c:358)) -- Greetings Jochen Kalmbach Microsoft MVP VC++ My blog about Win32 and .NET http://blog.kalmbachnet.de/ PS: Please mark an answer as "answered" if it helped!!!
  • alazela

    Hi hyslopc!
    I think this is simply a miss on the part of the CRT.  If I change my code so that it doesn't delete the corrupt block, but just lets it sit there, then within 1024 allocations later, _CrtCheckMemory() gets called, and it *does* log the file/line info (on line 1607 of dbgrpt.c).  So the CRT behaves inconsistently depending on how the problem is detected.  I am going to report this to MS as a bug.
    What info is the the "_CrtCheckMemory" better than in the case of "delete"
    -- 
    Greetings
     Jochen Kalmbach
     Microsoft MVP VC++
    
      My blog about Win32 and .NET
      http://blog.kalmbachnet.de/
      
    PS: Please mark an answer as "answered" if it helped!!!

  • restore

    I just ran a test of the VS 2005 beta 2 debug CRT library

    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_CHECK_EVERY_1024_DF | _CRTDBG_CHECK_CRT_DF);

    char * Test = new char[3];

    Test[3] = '\0'; // Cause memory corruption

    delete Test;

    This results in a dialog box being shown which says that a heap overwrite occured with allocation X at location Y.  No really useful information such as the filename/line number where the allocation occurred, or the number of bytes allocated.

    If I jump into the debugger at that point, I see that the message was generated by line 1171 of dbgheap.c, and that it was generated from a _CrtMemBlockHeader structure which includes all of the useful info that I has hoped would be displayed.

    So my question to the VC++ RTL guys is: you have the file/line info right there, why the heck don't you include it in the message


  • AdLearning.Net

    The debug CRT has a _CrtMemBlockHeader structure which includes the filename, the line number within the file where the allocation took place, and the number of bytes allocated.  If you do as I did, you will see this clearly in the debugger.  All the info is there, and it is reported just fine if you call _CrtCheckMemory().  The bug is that free_dbg_nolock() doesn't include the same logic that _CrtCheckMemory() does.  I have now reported this to Microsoft as bug FDBK24744 - hopefully they fix it.
  • VS2005 debug CRT does not report file/line info for heap corruption