Visual Leak Detector报告泄漏了一个int*的40个字节

use*_*er1 7 c++ memory-leaks visual-leak-detector

这是我的计划

#include <vld.h>

using namespace std;

int main() {
    int* p = new int(100);
}
Run Code Online (Sandbox Code Playgroud)

视觉泄漏探测器报告

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).
Run Code Online (Sandbox Code Playgroud)

为什么40 bytes内存泄漏,它确实应该是4 bytes.

谁能解释一下这里发生了什么?

xry*_*669 5

首先,当你要求分配4个字节时,很可能你会得到一个更大的块(这是安全的,因为你应该只使用你要求的4个字节).

为什么?

  1. 分配大小必须存储在某个地方(考虑new X[count]大小写,并且delete[]必须调用countX的析构函数

  2. 然后,堆分配通常通过堆的递归分段来完成,例如Buddy_memory_allocation.这是因为您希望尽可能低的开销(即,与真正分配的字节相比,用于管理分配的字节数).你需要记住是否使用了一些内存块.

  3. 调试也可能会增加分配大小.在Visual Studio上,malloc/free函数在返回的指针之前插入4个字节,其中包含"内存保护"(如(0xDDDDDDDD)),并在请求的大小之后为另一个内存保护分配4个字节.当您调用malloc或free(间接,new和delete)时,堆处理程序的代码会检查guard并声明它们未被修改.如果是,它会停止你的程序,所以你可以看到"周围"修改内存的地方.IIRC,0xCDCDCDCD用于填充分配区域,0xFEEEFEEE用于填充释放区域但是块尚未返回到系统,并0xDDDDDDDD用于边界.

因此,即使您只使用"4",您接收的块的大小似乎也是40个字节(可能更多).VLD不跟踪您的代码,它拦截内存管理功能(如malloc/free),并构建分配的每个块的列表.解析此列表以在释放元素时删除元素.终止后,列出任何剩余项目.

因此收到的malloc调用可能来自于将::operator new所请求的大小扩大到40字节,或者可能在VLD中添加32字节的块来跟踪"分配请求".

在查看VLD源代码(特别是vldnew函数)之后,它为每个分配分配一个标头:

vldblockheader_t *header = (vldblockheader_t*)RtlAllocateHeap(g_vldHeap, 0x0, size + sizeof(vldblockheader_t))
Run Code Online (Sandbox Code Playgroud)

可能vldblockheader_t在你的情况下是36个字节.

  • 好的,我已经搜索了VLD源代码,这确实是VLD开销.请看我的编辑 (2认同)