c++memory-leaksvisual-leak-detector

Visual Leak Detector reports 40 bytes leaked for one int*


Here's my program

#include <vld.h>

using namespace std;

int main() {
    int* p = new int(100);
}

Visual Leak Detector Report

Visual Leak Detector Version 2.3 installed.
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 1 at 0x00891B60: 4 bytes ----------
  Call Stack:
    c:\xxx\documents\visual studio 2010\projects\stl1\stl1\stl1.cpp (11): stl1.exe!main + 0x7 bytes
    f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (555): stl1.exe!__tmainCRTStartup + 0x19 bytes
    f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (371): stl1.exe!mainCRTStartup
    0x76B7338A (File and line number not available): kernel32.dll!BaseThreadInitThunk + 0x12 bytes
    0x774B97F2 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x63 bytes
    0x774B97C5 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x36 bytes
  Data:
    64 00 00 00                                                  d....... ........


Visual Leak Detector detected 1 memory leak (40 bytes).
Largest number used: 40 bytes.
Total allocations: 40 bytes.
Visual Leak Detector is now exiting.
The program '[8992] stl1.exe: Native' has exited with code 0 (0x0).

Why 40 bytes memory leak, it really should have been 4 bytes.

Can anyone explain what is going on here?


Solution

  • First, when you ask for 4 bytes allocation, chances are high that you'll always get a larger block (which is safe, because you are supposed to use only the 4 bytes you've asked for).

    Why?

    1. Allocation size has to be stored somewhere (think about new X[count] case, and delete[] that must call count times the destructor of X

    2. Then, heap allocation is usually done by recursive fragmenting of the heap for example the Buddy_memory_allocation. This is because you want as low overhead as possible (that is, the amount of bytes used for managing allocations compared to the really allocated bytes). You need to remember if some block of memory is used or not.

    3. Debugging might also add allocation size. On Visual Studio, the malloc / free function insert 4 bytes before the returned pointer with a "memory guard" like (0xDDDDDDDD), and allocate 4 more bytes too for another memory guard after the requested size. When you call malloc or free (indirectly, new and delete), the heap handler's code checks the guard and assert that they are not modified. If they are, it stops your program so you can see "around" the place where the memory was modified. IIRC, 0xCDCDCDCD is used for filling allocated area, 0xFEEEFEEE is used to fill freed area but the block is not returned yet to the system, and 0xDDDDDDDD are used for boundaries.

    So it seems that the size of the block you're receiving is 40 bytes (maybe more) even if you only use "4". VLD does not track your code, it intercept memory management functions (like malloc/free), and build a list of each block allocated. This list is parsed to remove elements when they are freed. Upon termination, any remaining item is listed.

    So the malloc call received likely comes from a ::operator new which enlarged the requested size to 40 bytes, or maybe a block of 32 bytes is added in VLD to track the "allocation request".

    After looking at VLD source code, specifically the vldnew function, it allocate a header for each allocation:

    vldblockheader_t *header = (vldblockheader_t*)RtlAllocateHeap(g_vldHeap, 0x0, size + sizeof(vldblockheader_t))
    

    Likely, the vldblockheader_t is 36 bytes in your case.