user1
user1

Reputation: 4131

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?

Upvotes: 7

Views: 1019

Answers (2)

xryl669
xryl669

Reputation: 3584

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.

Upvotes: 5

Ziezi
Ziezi

Reputation: 6457

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

It has to do both with additional information about the dynamically allocated object and the efficient1, 2 management of the dynamical(heap) memory.

Regarding the former, there should be information available so that the allocated heap memory is freed after the object life ends.

As for the latter, there is something called capacity and it is not necessarily to be equal to the allocated size. It can be equal or greater, with the extra space allowing to accommodate for growth without the need to reallocate on each insertion.

Notice that this capacity does not suppose a limit on the size of the type, in your case int.

Example:

vectors are sequence containers representing arrays that can change in size. Internally, vectors use a dynamically allocated array to store their elements. A call to the following three vector member functions:

  • size()

  • max_size()

  • capacity()

will return different values and will provide you with some insight of the strategy used when allocating heap memory.


1. If the initially allocated object needs to grow it may be necessary to be entirely reallocated, instead of expanded to neighbouring/contiguous memory section. Involving a lot of operations.

2. Extra padding could be added for memory alignment (multiples of 4 bytes, so that it can be read with a less memory accesses)

Upvotes: 0

Related Questions