Inside CRT: Debug Heap Management

When you compile a debug build of your program with Visual Studio and run it in debugger, you can see that the memory allocated or deallocated has funny values, such as 0xCDCDCDCD or 0xDDDDDDDD. This is the result of the work Microsoft has put in to detect memory corruption and leaks in the Win32 platform. In this article, I will explain how memory allocation/deallocation is done via new/delete or malloc/free.

First, I will explain what all these values that you see, like CD, DD, and so forth, mean.

Value Name Description
0xCD Clean Memory Allocated memory via malloc or new but never written by the application.
0xDD Dead Memory Memory that has been released with delete or free. It is used to detect writing through dangling pointers.
0xFD Fence Memory Also known as "no mans land." This is used to wrap the allocated memory (like surrounding it with fences) and is used to detect indexing arrays out of bounds.
0xAB (Allocated Block?) Memory allocated by LocalAlloc().
0xBAADF00D Bad Food Memory allocated by LocalAlloc() with LMEM_FIXED, but not yet written to.
0xCC   When the code is compiled with the /GZ option, uninitialized variables are automatically assigned to this value (at byte level).

If you take a look at DBGHEAP.C, you can see how some of these values are defined:

static unsigned char _bNoMansLandFill = 0xFD;   /* fill no-man's land with this */
static unsigned char _bDeadLandFill   = 0xDD;   /* fill free objects with this */
static unsigned char _bCleanLandFill  = 0xCD;   /* fill new objects with this */

Before going any further, take a look at the memory management function that I will refer in this article.

Function Description
malloc C/C++ function that allocates a block of memory from the heap. The implementation of the C++ operator new is based on malloc.
_malloc_dbg Debug version of malloc; only available in the debug versions of the run-time libraries. _malloc_dbg is a debug version of the malloc function. When _DEBUG is not defined, each call to _malloc_dbg is reduced to a call to malloc. Both malloc and _malloc_dbg allocate a block of memory in the base heap, but _malloc_dbg offers several debugging features: buffers on either side of the user portion of the block to test for leaks, a block type parameter to track specific allocation types, and filename/linenumber information to determine the origin of allocation requests.
free C/C++ function that frees an allocated block. The implementation of C++ operator delete is based on free.
_free_dbg Debug version of free; only available in the debug versions of the run-time libraries. The _free_dbg function is a debug version of the free function. When _DEBUG is not defined, each call to _free_dbg is reduced to a call to free. Both free and _free_dbg free a memory block in the base heap, but _free_dbg accommodates two debugging features: the ability to keep freed blocks in the heap's linked list to simulate low memory conditions and a block type parameter to free specific allocation types.
LocalAlloc
GlobalAlloc
Win32 API to allocate the specified number of bytes from the heap. Windows memory management does not provide a separate local heap and global heap.
LocalFree
GlobalFree
Win32 API free the specified local memory object and invalidates its handle.
HeapAlloc Win32 API allocates a block of memory from a heap. The allocated memory is not movable.
HeapFree Win32 API frees a memory block allocated from a heap by the HeapAlloc or HeapReAlloc function.

There are many other functions that deal with memory management. For a complete view please refer to MSDN.

Note: Because this article is about memory management in a debug build, all the references to malloc and free in the following are actually references to their debug versions, _malloc_dbg and _free_dbg.

Compile the following code and run it in the debugger, walking step by step into it to see how memory is allocated and deallocated.

int main(int argc, char* argv[])
{
   char *buffer = new char[12];

   delete [] buffer;

   return 0;
}

Here, 12 bytes are dynamically allocated, but the CRT allocates more than that by wrapping the allocated block with bookkeeping information. For each allocated block, the CRT keeps information in a structure called _CrtMemBlockHeader, which is declared in DBGINT.H:

#define nNoMansLandSize 4

typedef struct _CrtMemBlockHeader
{
        struct _CrtMemBlockHeader * pBlockHeaderNext;
        struct _CrtMemBlockHeader * pBlockHeaderPrev;
        char *                      szFileName;
        int                         nLine;
        size_t                      nDataSize;
        int                         nBlockUse;
        long                        lRequest;
        unsigned char               gap[nNoMansLandSize];
        /* followed by:
         *  unsigned char           data[nDataSize];
         *  unsigned char           anotherGap[nNoMansLandSize];
         */

} _CrtMemBlockHeader;

It stores the following information:

Field Description
pBlockHeaderNext A pointer to the next block allocated, but next means the previous allocated block because the list is seen as a stack, with the latest allocated block at the top.
pBlockHeaderPrev A pointer to the previous block allocated; this means the block that was allocated after the current block.
szFileName A pointer to the name of the file in which the call to malloc was made, if known.
nLine The line in the source file indicated by szFileName at which the call to malloc was made, if known.
nDataSize Number of bytes requested
nBlockUse 0 - Freed block, but not released back to the Win32 heap
1 - Normal block (allocated with new/malloc)
2 - CRT blocks, allocated by CRT for its own use
lRequest Counter incremented with each allocation
gap A zone of 4 bytes (in the current implementation) filled with 0xFD, fencing the data block, of nDataSize bytes. Another block filled with 0xFD of the same size follows the data.

Most of the work of heap block allocation and deallocation are made by HeapAlloc() and HeapFree(). When you request 12 bytes to be allocated on the heap, malloc() will call HeapAlloc(), requesting 36 more bytes.

blockSize = sizeof(_CrtMemBlockHeader) + nSize + nNoMansLandSize;

malloc requests space for the 12 bytes we need (nSize), plus 32 bytes for the _CrtMemBlockHeader structure and another nNoMansLandSize bytes (4 bytes) to fence the data zone and close the gap.

But, HeapAlloc() will allocate even more bytes: 8 bytes below the requested block (that is, at a lower address) and 32 above it (that is, at a bigger address). It also initializes the requested block to 0xBAADF00D (bad food).

Then, malloc() fills the _CrtMemBlockHeader block with information and initializes the data block with 0xCD and no mans land with 0xFD.

Here is a table that shows how memory looks after the call to HeapAlloc() and after malloc() returns. For a complete situation, see the last table. (Note: All values are in hex.)

Address after HeapAlloc() after malloc()
00320FD8
00320FDC
00320FE0
00320FE4
00320FE8
00320FEC
00320FF0
00320FF4
00320FF8
00320FFC
00321000
00321004
00321008
0032100C
00321010
00321014
00321018
0032101C
00321020
00321024
00321028
0032102C
09 00 09 01
E8 07 18 00
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
AB AB AB AB
AB AB AB AB
00 00 00 00
00 00 00 00
79 00 09 00
EE 04 EE 00
40 05 32 00
40 05 32 00
09 00 09 01
E8 07 18 00
98 07 32 00
00 00 00 00
00 00 00 00
00 00 00 00
0C 00 00 00
01 00 00 00
2E 00 00 00
FD FD FD FD
CD CD CD CD
CD CD CD CD
CD CD CD CD
FD FD FD FD
AB AB AB AB
AB AB AB AB
00 00 00 00
00 00 00 00
79 00 09 00
EE 04 EE 00
40 05 32 00
40 05 32 00

Colors:

  • Green: win32 bookkeeping info
  • Blue: block size requested by malloc and filled with bad food
  • Magenta: _CrtMemBlockHeader block
  • Red: no mans land
  • Black: requested data block

In this example, after the call to malloc() returns, buffer will point to memory address 0x00321000.

When you call delete/free, the CRT will set the block it requested from HeapAlloc() to 0xDD, indicating this is a free zone. Normally after this, free() will call HeapFree() to give back the block to the Win32 heap, in which case the block will be overwritten with 0xFEEEEEEE, to indicate Win32 heap free memory.

You can avoid this by using the CRTDBG_DELAY_FREE_MEM_DF flag to _CrtSetDbgFlag(). It prevents memory from actually being freed, as for simulating low-memory conditions. When this bit is on, freed blocks are kept in the debug heap's linked list but are marked as _FREE_BLOCK. This is useful if you want to detect dangling pointers errors, which can be done by verifying if the freed block is written with 0xDD pattern or something else. Use _CrtCheckMemory() to verify the heap.s integrity.

The next table shows how the memory looks during the free(), before HeapFree() is called and afterwards.

Address Before HeapFree() After HeapFree()
00320FD8
00320FDC
00320FE0
00320FE4
00320FE8
00320FEC
00320FF0
00320FF4
00320FF8
00320FFC
00321000
00321004
00321008
0032100C
00321010
00321014
00321018
0032101C
00321020
00321024
00321028
0032102C
09 00 09 01
5E 07 18 00
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
AB AB AB AB
AB AB AB AB
00 00 00 00
00 00 00 00
79 00 09 00
EE 04 EE 00
40 05 32 00
40 05 32 00
82 00 09 01
5E 04 18 00
E0 2B 32 00
78 01 32 00
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE

Colors:

  • Green: win32 bookkeeping info
  • Blue: CRT block filled with dead memory
  • Gray: memory given back to win32 heap

The two tables above are put in a single, more detailed, table below:

Address (hex) Offset HeapAlloc malloc Free before HeapFree Free after HeapFree Description
00320FD8 -40 01090009 01090009 01090009 01090082 Win32 Heap info
00320FDC -36 001807E8 001807E8 0018075E 0018045E Win32 Heap info
00320FE0 -32 BAADF00D 00320798 DDDDDDDD 00322BE0 pBlockHeaderNext
00320FE4 -28 BAADF00D 00000000 DDDDDDDD 00320178 pBlockHeaderPrev
00320FE8 -24 BAADF00D 00000000 DDDDDDDD FEEEEEEE szFileName
00320FEC -20 BAADF00D 00000000 DDDDDDDD FEEEEEEE nLine
00320FF0 -16 BAADF00D 0000000C DDDDDDDD FEEEEEEE nDataSize
00320FF4 -12 BAADF00D 00000001 DDDDDDDD FEEEEEEE nBlockUse
00320FF8 -8 BAADF00D 0000002E DDDDDDDD FEEEEEEE lRequest
00320FFC -4 BAADF00D FDFDFDFD DDDDDDDD FEEEEEEE gap (no mans land)
00321000 0 BAADF00D CDCDCDCD DDDDDDDD FEEEEEEE Data requested
00321004 +4 BAADF00D CDCDCDCD DDDDDDDD FEEEEEEE Data requested
00321008 +8 BAADF00D CDCDCDCD DDDDDDDD FEEEEEEE Data requested
0032100C +12 BAADF00D FDFDFDFD DDDDDDDD FEEEEEEE No mans land
00321010 +16 ABABABAB ABABABAB ABABABAB FEEEEEEE Win32 Heap info
00321014 +20 ABABABAB ABABABAB ABABABAB FEEEEEEE Win32 Heap info
00321018 +24 00000000 00000000 00000000 FEEEEEEE Win32 Heap info
0032101C +28 00000000 00000000 00000000 FEEEEEEE Win32 Heap info
00321020 +32 00090079 00090079 00090079 FEEEEEEE Win32 Heap info
00321024 +36 00EE04EE 00EE04EE 00EE04EE FEEEEEEE Win32 Heap info
00321028 +40 00320540 00320540 00320540 FEEEEEEE Win32 Heap info
0032102C +44 00320540 00320540 00320540 FEEEEEEE Win32 Heap info


About the Author

Marius Bancila

Marius Bancila is a Microsoft MVP for VC++. He works as a software developer for a Norwegian-based company. He is mainly focused on building desktop applications with MFC and VC#. He keeps a blog at www.mariusbancila.ro/blog, focused on Windows programming. He is the co-founder of codexpert.ro, a community for Romanian C++/VC++ programmers.

Comments

  • Savez-vous comment nettoyer un GHD Styler?

    Posted by ziiitv768 on 07/16/2013 07:27am

    Ces produits de beauté GHD sont adaptés pour obtenir à peu près n'importe quel type de cheveux parfaite stil.Du peut profiter de défriser les cheveux GHD attirer l'attention sur les traits de votre visage que vous préféreriez être remarqué plus. Par exemple, si vous avez des pommettes bien défini puis se redressant, votre frange ou la couche supérieure de cheveux pour mettre l'accent non seulement vos pommettes, mais même dans les yeux. Les femmes qui ont les cheveux volumineux mais ils ont peur que ces défrisants peuvent leur faire perdre leur rebond peuvent bomber dehors seule la couche supérieure pour être les cheveux très lisse sur le dessus et leurs mèches ondulées et plein d'entrain habituel ci-dessous. [url=http://ghdpascherferfr.blinkweb.com/]lisseur ghd styler[/url] Récemment a eu le GHD rose, édition limitée pur / sombre sous le nom de GHD MK4 (IV) établir GHD au pouvoir se rapproche uangripelig posisjon au-dessus av portée marché opp-et-vient à défrisants professionnels avec plusieurs funksjoner utile, entre autres choses, un câble sterk supplémentaire , quelque chose qui muliggjør plus frihet lorsque vous stockez ces cils et les boucles et les dernières plaines de la technologie chauffage infra-rouge signifie que hastigheten sur gjennomføring chaleur av et garder au chaud le temps lengre dans le MK4 céramique Plater, ytterligere aidera à veiller à y serrure en minéraux, cheveux ferries et l'humidité dans le ditt de cheveux pour lengre période, un gi cheveux ditt silkemykt, éclat de style et sans électricité statique. Les nouvelles plaines de maintien rondes signifient y Skape styles complexes comme les boucles et les cils sont plus faciles y do.Another avantage le client obtient avec cette nouvelle GHD MK4 (IV) Styler & Horizontal Tang est un DVD qui donne instruksjoner et spesielle conseils pour y obtenir le beste visant à cheveux. Vous pouvez accéder à expérimenter et forskjellig style de cheveux pour la deuxième journée. [url=http://ghdpascherfer.hpage.com/]ghd pas cher[/url] Les tôles moyennes, il est possible d'être aussi créatifs et obtenir le look désiré, si vous le voulez, boucles ultra lisses gonflables ou de grands radiateurs en céramique bølger.Avanserte et plates-La surface en aluminium de style ultime pour un poil brillant sans électricité statique en douceur. la plaque étroite est idéal pour les coiffures courtes et est l'outil ultime et frange de style aussi à créer plus résistants redresseur d'or krøller.Denne de HH Simonsen est petit, élégant et incroyablement intelligent. Le redresseur est parfait pour votre sac à main ou à garder dans le kit lorsque vous êtes sur la route!

    Reply
  • More concessions with herveleger, more designate someone back on his!

    Posted by Mrtopflisax on 04/29/2013 06:58am

    wenchpicayune shaverbe in bond withshoplifteulogisticapportion in

    Reply
  • Jordan shoes mentioned Gene to pay off the manufacturer, a segment of Nike

    Posted by TaddyGaffic on 04/22/2013 05:44pm

    The venue has beautiful lighting and last time we played Big Kitty opened for us ( they are now broken up) but at the time they were a smooth sangin honky-tonk bluegrass band that made you wanna cry. This time our openers were The Nim Nims a local band that sounds [url=http://fossilsdirect.co.uk/glossarey.cfm]nike huarache[/url] kinda Christian but not. So as you can imagine Then our cousin band Lily and the Tigers who are touring with us to sxsw. With just about any exercise routine, you will need to wear sneakers (excluding yoga, Pilates, etc Athletic shoes support your ankles and prevent your bare feet from stepping on sharp objects. Plain and simply put, they help you avoid injury. However, simply jumping into your latest pair of kicks doesn mean you [url=http://northernroofing.co.uk/roofins.cfm]nike free run 3[/url] ready to hit the gym. Instead of "outdoors", think "hiking". Instead of hiking, think "hiking boots". If you know what you are talking about and enjoy the subject, it will be easier to talk to people (online or in person) and transmit your message of enjoyment to them. You need some arch support to conform the rough shape roads. Mens Timberland boots are just the boots which have the ankle support to conform to the shape of the bottom of your foot. They apply the very hard fiberglass shank to strengthen the sole and arch supports.. In [url=http://markwarren.org.uk/goodbuy.cfm]nike free run uk[/url] midfield, Frank Lampard, Raul Meireles and Rafael Ramirez lined up. Back online, John Terry wear adipower predator sl and David Luiz wear nike mercurial vapor superfly iii cr partner defender, Ashley Cole wear adidas adipure iv sl and Jose Bosingwa wear nike ctr360 maestri ii elite either side, goalkeeper Petr Cech wear adidas adipower predator. 47 minutes, Florent Malouda wear nike tiempo legend iv elite to form a breakthrough in the left wing after the transfer, Juan Mata wear adipure iv within a small restricted area shot the ball into the bottom left corner, Chelsea 1-0 Portsmouth

    Reply
  • manner mlb jerseys

    Posted by xaldwinecqq on 03/12/2013 12:38pm

    clarisonic mia 2 outlet clarisonic online shop discount clarisonic clarisonic outlet store clarisonic canada cheap clarisonic mia canada cheap clarisonic sale uk clarisonic sale uk authentic nfl jerseys wholesale nhl jerseys

    Reply
  • other

    Posted by idsantos on 08/14/2012 02:16am

    I know it is an old artikle, but the 0xCDCDCDCD and 0xFDFDFDFD is a great way to debug a pointer or even better an array of pointers. Great artikel by the way.

    Reply
  • Great !!

    Posted by thomus07 on 12/15/2007 04:14am

    Really admire this article. I also saw few of your posts in individual FAQs which cleared me in many ways. Your focus on "COMMONLY KNOWN UNKNOWNS" is simply the great. Go ahead !!. I rated excellent and thats what I could do.

    Reply
  • confused.... :(

    Posted by julvar on 07/10/2007 03:30pm

    I am in an very confusing situation.. and maybe you can help me. I have a code that works fine in debug version within the VS2005 IDE but crashes when I run the debug version in the command prompt. what's even more confusing is that the release version works fine (in both IDE and command prompt) do you have any idea what's causing this ? i have no idea how to even begin solving this !

    • not the appropriate place

      Posted by cilu on 07/11/2007 02:41am

      This is not the appropriate place to address this questions. Ask it on a forum, such as www.codeguru.com/forum. Please post only article-related comments here. Thank you.

      Reply
    Reply
  • one doubt

    Posted by sonali_ncst on 12/27/2005 06:07am

    when do we get "user breakpoint called from code 0x77f767cd" error?

    Reply
  • Great article

    Posted by mdalessio on 04/19/2005 11:40am

    Some really invaluable knowledge in this article. Thanks for taking the time to write it up. I'm recommending it to my team of developers!

    Reply
  • Interesting!

    Posted by AlexQ on 04/06/2005 12:25pm

    very nice tutorial. I think that you have still place for an advanced example to show the (obvious) advantages of knowing this while debugging (a heap overflow analysis would be great). Thx. Alex

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: November 20, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT Are you wanting to target two or more platforms such as iOS, Android, and/or Windows? You are not alone. 90% of enterprises today are targeting two or more platforms. Attend this eSeminar to discover how mobile app developers can rely on one IDE to create applications across platforms and approaches (web, native, and/or hybrid), saving time, money, and effort and introducing apps to market faster. You'll learn the trade-offs for gaining long …

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds