Visual Leak Detector reports 40 bytes of leak for one int *

Here is my program

#include <vld.h> using namespace std; int main() { int* p = new int(100); } 

Leak Detection 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 be 4 bytes .

Can someone explain what is going on here?

+7
c ++ memory-leaks visual-leak-detector
source share
2 answers

First, when you request a 4-byte allocation, it is likely that you will always get a larger block (this is safe because you should only use the 4 bytes that you requested).

Why?

  • The size of the distribution should be saved somewhere (think about the case of new X[count] and delete[] ), which should call count times the destructor X

  • Heap allocation is then typically done by recursively fragmenting the heap, such as Buddy_memory_allocation . This is because you want as little overhead as possible (i.e. the number of bytes used to manage allocations compared to the actually allocated bytes). You must remember if any memory block is used.

  • Debugging can also add placement size. In Visual Studio, the malloc / free function inserts 4 bytes before the returned pointer with a "memory protection" like ( 0xDDDDDDDD ), and allocates another 4 bytes to another memory protection device after the requested size. When you call malloc or for free (indirectly, new and delete), the heap handler code checks the guard and claims that they are not changed. If they are, it stops your program so that you can see "around" the place where the memory was changed. IIRC, 0xCDCDCDCD used to fill the selected area, 0xFEEEFEEE used to fill the freed area, but the block has not yet returned to the system, and 0xDDDDDDDD used for borders.

So the block size you get is 40 bytes (maybe more), even if you use only β€œ4”. VLD does not track your code; it intercepts memory management functions (for example, malloc/free ) and builds a list of each allocated block. This list is parsed to remove items when they are freed. Upon completion, any remaining item is listed.

Thus, the received call to malloc most likely comes from ::operator new , which increased the requested size to 40 bytes, or, perhaps, a block of 32 bytes was added to the VLD to track the "distribution request".

After viewing the VLD source code , in particular the vldnew function, it selects a header for each selection:

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

Probably vldblockheader_t is 36 bytes in your case.

+5
source share

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

It should do both additional information about a dynamically distributed object and effective management of dynamic (heap) memory 1, 2 .

As for the first, information must be available so that the allocated heap memory is freed after the end of the object's life.

As for the latter, there is something called bandwidth, and it does not have to be equal to the allocated size. It can be equal or large, with additional space that allows you to take into account growth without the need for redistribution with each insert.

Please note that this capacity does not allow restrictions on the type size in your int case.

Example:

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

  • size()

  • max_size()

  • capacity()

will return different values ​​and give you some idea of ​​the strategy used to allocate heap memory.


1. If the originally allocated object is to grow, it may be required that it be completely redistributed rather than expanded into an adjacent / continuous memory section. Involving a large number of operations.

2. To align the memory, an additional addition can be added (multiplicity of 4 bytes, so that it can be read with less access to memory)

0
source share

All Articles