内存管理和调试堆

本主题适用于:

版本

Visual Basic

C#

F#

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 填充。

请参见

其他资源

CRT 调试堆