Setting Breakpoints on a Memory Allocation Number
上一篇文章介绍了 CRT Memory Detection 的概念和基本用法, 那么这篇文章将介绍一种高级调试技术 --- memory allocation breakpoints. ( 以下讨论均在 debug 模式前提下 )
基本概念:
首先让回顾一下完整的 memory dump 的输出格式:
其中对本文有用的信息是 内存分配号. 我们可以理解这个内存分配号为: 分配内存块的序号.
上图可见, 地址 0x005FB960 是第 120 次分配的内存块, 0x005FB9A0 是第 121 次内存分配.
调试方法:
在 vs 中, 有一种断点, 叫做内存块号断点, 该断点可以再第 n 此堆内存分配的时候打断程序执行.
我们通过 `_CrtDumpMemoryLeaks();` 找到了泄露点以后, 就可以根据泄露号对该泄露进行断点:
有两种设置方法:
1. _CrtSetBreakAlloc(18);
2. _crtBreakAlloc = 18;
上述两种方法等价, F5 运行效果如下图所示:
最后再补充一下关于块类型 ( block type ) 的概念: http://support.tenasys.com/INtimeHelp_5/abt_debugheapblocktypes.html
每一个 debug heap 都被赋予了一个 type, 一共有 5 种:
a) _NORMAL_BLOCK: 这种类型就是 malloc, realloc 等函数的默认分配方式.
b) _CRT_BLOCK: 这种类型是 CRT 内部使用的特定类型. 也就是 CRT为了避免和我们的 block 相混淆, 所以单独设置了一个自己的类型 id. 我们的程序中, 不应该是用这种类型.
c) _CLIENT_BLOCK: 这种类型是用户自定义的类型. 而且它可以左移 16 位后和 sub type 进行 或运算 ( _CLIENT_BLOCK|(MYSUBTYPE<<16) ), 因此可以生成 0x10000 个自定义的 type. 这有助于我们在代码中使用类似 `new ( _MY_CLIENT_BLOCK , __FILE__ , __LINE__ )` 快速的找到 type 为 _MY_CLIENT_BLOCK 的内存信息.
d) _FREE_BLOCK: 一般的内存块被释放后, 都会从堆列表中被移除, 但是如果标记了这个标识的内存块, 被释放后会继续留在对列表中, 但是被标记为 free 状态, 并且内存块被写入 0xDD. 此标记被用于检查被释放的内存是否仍然被写入数据, 以及模拟内存不足的情况.
e) _IGNORE_BLOCK: 原文我没读懂, 也不知道是干嘛的, 感觉上和我们日常生活没太大关系, 原文如下, 请读者自行斟酌: It is possible to turn off the debug heap operations for a period of time. During this time, memory blocks are kept on the list, but are marked as Ignore blocks.