Visual Leak Detector 报告一个 int* 有 40 个字节泄漏
Visual Leak Detector reports 40 bytes leaked for one int*
这是我的程序
#include <vld.h>
using namespace std;
int main() {
int* p = new int(100);
}
视觉检漏报告
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).
为什么40 bytes
内存泄漏,确实应该是4 bytes
。
谁能解释一下这是怎么回事?
首先,当您要求分配 4 个字节时,您总是会得到一个更大的块的可能性很高(这是安全的,因为您应该只使用您要求的 4 个字节)。
为什么?
分配大小必须存储在某处(考虑 new X[count]
情况,并且 delete[]
必须调用 count
次 X[=23= 的析构函数]
然后,堆分配通常通过堆的递归碎片来完成,例如the Buddy_memory_allocation。
这是因为您希望开销尽可能低(即,用于管理分配的字节数与实际分配的字节数相比)。您需要记住是否使用了某些内存块。
调试也可能会增加分配大小。在 Visual Studio 上,malloc / free 函数在返回的指针之前插入 4 个字节,并带有一个 "memory guard",如 (0xDDDDDDDD
),并在请求的大小之后为另一个内存保护分配另外 4 个字节。当您调用 malloc 或 free(间接调用 new 和 delete)时,堆处理程序的代码会检查守卫并断言它们未被修改。如果是,它会停止你的程序,这样你就可以看到 "around" 内存被修改的地方。 IIRC,0xCDCDCDCD
用于填充分配区域,0xFEEEFEEE
用于填充释放区域但块尚未返回系统,0xDDDDDDDD
用于边界。
所以即使您只使用“4”,您收到的块的大小似乎也是 40 个字节(可能更多)。
VLD 不会跟踪您的代码,它会拦截内存管理函数(如 malloc/free
),并构建每个已分配块的列表。解析此列表以在释放元素时将其删除。终止后,将列出任何剩余项目。
因此收到的 malloc 调用可能来自 ::operator new
,它将请求的大小扩大到 40 字节,或者可能在 VLD 中添加了一个 32 字节的块来跟踪 "allocation request"。
看了VLD source code后,具体是vldnew函数,它为每个分配分配了一个header:
vldblockheader_t *header = (vldblockheader_t*)RtlAllocateHeap(g_vldHeap, 0x0, size + sizeof(vldblockheader_t))
在您的情况下,vldblockheader_t
可能是 36 个字节。
Why 40 bytes memory leak, it really should have been 4 bytes.
它必须处理有关动态分配对象的附加信息和动态(堆)内存的高效1、2管理。
关于前者,应该有可用的信息,以便在对象生命周期结束后释放分配的堆内存。
至于后者,有一个叫做容量的东西,它不一定等于分配的大小。它可以等于或更大,额外的 space 允许适应增长而无需在每次插入时重新分配。
请注意,此容量不假设类型大小的限制,在您的情况下 int
。
示例:
vector
s 是序列容器,表示可以改变大小的数组。在内部,向量使用动态分配的数组来存储它们的元素。
调用以下三个 vector
成员函数:
size()
max_size()
capacity()
将 return 不同的值,并会让您深入了解分配堆内存时使用的策略。
1.如果最初分配的对象需要增长,则可能需要完全重新分配,而不是扩展到 neighbouring/contiguous 内存部分。涉及很多操作。
2。可以添加额外的填充以进行内存对齐(4 字节的倍数,以便可以用较少的内存访问来读取它)
这是我的程序
#include <vld.h>
using namespace std;
int main() {
int* p = new int(100);
}
视觉检漏报告
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).
为什么40 bytes
内存泄漏,确实应该是4 bytes
。
谁能解释一下这是怎么回事?
首先,当您要求分配 4 个字节时,您总是会得到一个更大的块的可能性很高(这是安全的,因为您应该只使用您要求的 4 个字节)。
为什么?
分配大小必须存储在某处(考虑
new X[count]
情况,并且delete[]
必须调用count
次 X[=23= 的析构函数]然后,堆分配通常通过堆的递归碎片来完成,例如the Buddy_memory_allocation。 这是因为您希望开销尽可能低(即,用于管理分配的字节数与实际分配的字节数相比)。您需要记住是否使用了某些内存块。
调试也可能会增加分配大小。在 Visual Studio 上,malloc / free 函数在返回的指针之前插入 4 个字节,并带有一个 "memory guard",如 (
0xDDDDDDDD
),并在请求的大小之后为另一个内存保护分配另外 4 个字节。当您调用 malloc 或 free(间接调用 new 和 delete)时,堆处理程序的代码会检查守卫并断言它们未被修改。如果是,它会停止你的程序,这样你就可以看到 "around" 内存被修改的地方。 IIRC,0xCDCDCDCD
用于填充分配区域,0xFEEEFEEE
用于填充释放区域但块尚未返回系统,0xDDDDDDDD
用于边界。
所以即使您只使用“4”,您收到的块的大小似乎也是 40 个字节(可能更多)。
VLD 不会跟踪您的代码,它会拦截内存管理函数(如 malloc/free
),并构建每个已分配块的列表。解析此列表以在释放元素时将其删除。终止后,将列出任何剩余项目。
因此收到的 malloc 调用可能来自 ::operator new
,它将请求的大小扩大到 40 字节,或者可能在 VLD 中添加了一个 32 字节的块来跟踪 "allocation request"。
看了VLD source code后,具体是vldnew函数,它为每个分配分配了一个header:
vldblockheader_t *header = (vldblockheader_t*)RtlAllocateHeap(g_vldHeap, 0x0, size + sizeof(vldblockheader_t))
在您的情况下,vldblockheader_t
可能是 36 个字节。
Why 40 bytes memory leak, it really should have been 4 bytes.
它必须处理有关动态分配对象的附加信息和动态(堆)内存的高效1、2管理。
关于前者,应该有可用的信息,以便在对象生命周期结束后释放分配的堆内存。
至于后者,有一个叫做容量的东西,它不一定等于分配的大小。它可以等于或更大,额外的 space 允许适应增长而无需在每次插入时重新分配。
请注意,此容量不假设类型大小的限制,在您的情况下 int
。
示例:
vector
s 是序列容器,表示可以改变大小的数组。在内部,向量使用动态分配的数组来存储它们的元素。
调用以下三个 vector
成员函数:
size()
max_size()
capacity()
将 return 不同的值,并会让您深入了解分配堆内存时使用的策略。
1.如果最初分配的对象需要增长,则可能需要完全重新分配,而不是扩展到 neighbouring/contiguous 内存部分。涉及很多操作。
2。可以添加额外的填充以进行内存对齐(4 字节的倍数,以便可以用较少的内存访问来读取它)