对堆函数(如 malloc、free、calloc、realloc、new 和 delete)的所有调用均解析为这些函数在调试堆中运行的“Debug”版本。当释放内存块时,调试堆自动检查已分配区域两侧的缓冲区的完整性,如果发生改写,将发出错误报告。
使用调试堆
- 用 C 运行时库的“Debug”版本链接应用程序的调试版本。
从代码内部访问的调试堆功能
-
_CrtCheckMemory
- 许多调试堆功能必须从代码内访问。例如,可以使用对 _CrtCheckMemory 的调用来检查堆在任意点的完整性。该函数检查堆中的每个内存块,验证内存块头信息有效,并确认尚未修改缓冲区。 _CrtSetDbgFlag
-
可以使用内部标志 _crtDbgFlag 来控制调试堆跟踪分配的方式,该标志可使用 _CrtSetDbgFlag 函数进行读取和设置。通过更改该标志,可以指示调试堆在程序退出时检查内存泄漏,并报告检测到的所有泄漏。类似地,可以指定不将已释放的内存块从链接列表移除,以模拟内存不足情况。当检查堆时,将完全检查这些已释放的块,以确保它们未受打扰。
_crtDbgFlag 标志包含下列位域:
位域 默认值 说明 _CRTDBG_ALLOC_MEM_DF On 打开调试分配。当该位为 off 时,分配仍链接在一起,但它们的块类型为 _IGNORE_BLOCK。 _CRTDBG_DELAY_FREE_MEM_DF Off 防止实际释放内存,与模拟内存不足情况相同。当该位为 on 时,已释放块保留在调试堆的链接列表中,但标记为 _FREE_BLOCK,并用特殊字节值填充。 _CRTDBG_CHECK_ALWAYS_DF Off 导致每次分配和释放时均调用 _CrtCheckMemory。这将减慢执行,但可快速捕捉错误。 _CRTDBG_CHECK_CRT_DF Off 导致将标记为 _CRT_BLOCK 类型的块包括在泄漏检测和状态差异操作中。当该位为 off 时,在这些操作期间将忽略由运行时库内部使用的内存。 _CRTDBG_LEAK_CHECK_DF Off 导致在程序退出时通过调用 _CrtDumpMemoryLeaks 来执行泄漏检查。如果应用程序未能释放其所分配的所有内存,将生成错误报告。
更改一个或多个 _crtDbgFlag 位域并创建标志的新状态
- 在 newFlag 参数设置为 _CRTDBG_REPORT_FLAG 的情况下调用 _CrtSetDbgFlag(以获得当前的 _crtDbgFlag 状态),并在一个临时变量中存储返回值。
- 打开任何位,对临时变量与相应位屏蔽(在应用程序代码中由清单常数表示)进行 OR 运算(按位 | 符号)。
- 关闭其他位,对该变量与相应位屏蔽的 NOT(按位 ~ 符号)进行 AND 运算(按位 & 符号)。
- 在 newFlag 参数设置为临时变量中存储的值的情况下调用 _CrtSetDbgFlag,以创建 _crtDbgFlag 的新状态。
例如,下列代码行打开自动泄漏检测,关闭检查 _CRT_BLOCK 类型的块:
// Get current flag int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); // Turn on leak-checking bit tmpFlag |= _CRTDBG_LEAK_CHECK_DF; // Turn off CRT block checking bit tmpFlag &= ~_CRTDBG_CHECK_CRT_DF; // Set flag to the new value _CrtSetDbgFlag( tmpFlag );