内存管理和调试堆
更新:2007 年 11 月
本主题适用于:
版本 |
Visual Basic |
C# |
C++ |
Web Developer |
---|---|---|---|---|
速成版 |
仅限本机 |
|||
标准版 |
仅限本机 |
|||
专业团队版 |
仅限本机 |
表格图例:
适用 |
|
不适用 |
|
默认情况下隐藏的一条或多条命令。 |
程序员遇到的两种最常见而又难处理的问题是,覆盖已分配缓冲区的末尾以及内存泄漏(未能在不再需要某些分配后将其释放)。调试堆提供功能强大的工具来解决这类内存分配问题。
堆函数的“Debug”版本
堆函数的“Debug”版本调用“Release”版本中使用的标准版本或基版本。当请求内存块时,调试堆管理器从基堆分配略大于所请求的块的内存块,并返回指向该块中属于您的部分的指针。例如,假定应用程序包含调用:malloc( 10 )。在发行版本中,malloc 将调用基堆分配例程以请求分配 10 个字节。而在调试版本中,malloc 将调用 _malloc_dbg,该函数接着调用基堆分配例程以请求分配 10 个字节加上大约 36 个字节的额外内存。调试堆中产生的所有内存块在单个链接列表中连接起来,按照分配时间排序。
调试堆例程分配的附加内存的用途为:存储簿记信息,存储将调试内存块链接在一起的指针,以及形成数据两侧的小缓冲区(用于捕捉已分配区域的覆盖)。
当前,用于存储调试堆的簿记信息的块头结构在 DBGINT.H 头文件中声明如下:
typedef struct _CrtMemBlockHeader
{
// Pointer to the block allocated just before this one:
struct _CrtMemBlockHeader *pBlockHeaderNext;
// Pointer to the block allocated just after this one:
struct _CrtMemBlockHeader *pBlockHeaderPrev;
char *szFileName; // File name
int nLine; // Line number
size_t nDataSize; // Size of user block
int nBlockUse; // Type of block
long lRequest; // Allocation number
// Buffer just before (lower than) the user's memory:
unsigned char gap[nNoMansLandSize];
} _CrtMemBlockHeader;
/* In an actual memory block in the debug heap,
* this structure is followed by:
* unsigned char data[nDataSize];
* unsigned char anotherGap[nNoMansLandSize];
*/
该块的用户数据区域两侧的 NoMansLand 缓冲区当前大小为 4 个字节,并用调试堆例程所使用的已知字节值填充,以验证尚未覆盖用户内存块限制。调试堆还用已知值填充新的内存块。如果选择在堆的链接列表中保留已释放块(如下文所述),则这些已释放块也用已知值填充。当前,所用的实际字节值如下所示:
NoMansLand (0xFD)
应用程序所用内存两侧的“NoMansLand”缓冲区当前用 0xFD 填充。已释放块 (0xDD)
设置 _CRTDBG_DELAY_FREE_MEM_DF 标志后,调试堆的链接列表中保留未使用的已释放块当前用 0xDD 填充。新对象 (0xCD)
分配新对象时,这些对象用 0xCD 填充。