gflags检测程序heap问题

经常遇到一很郁闷的事情:发布给外部客户使用的程序crash了,把dump文件丢过来,对上pdb之后发现显示的调用栈莫名奇妙,或者是一个stl::vector的push_back调用,要么是在一个malloc分配内存或者new创建对象,甚至可能是一个字符串赋值;这些从代码上看怎么看都不应该导致程序crash的,这时候一般就是程序写内存越界,堆被破坏,导致显示的调用栈异常了。怎样才能确定导致程序异常的实际代码行呢?

用windows的debug tools中的global flags即gflags就可以了。gflags工作的时候,可以在用户每次分配内存的时候都在要分配的内存后边紧跟着分配一个保护区间(一般是一个虚拟页),一旦出现堆越界,就会立刻触发中断,这样就可以让调试器准确的定位代码行。

这里所说的立刻触发中断并不是必然的,取决于gflags的设置参数,如果启用了/unaligned参数,则会以不对齐的方式分配保护区间,这样即使越界一个字节都会立即触发异常;默认情况下分配保护区间是以对齐内存为单位的,因此在下面这种越界情况是检测不到的:

// 越界不能超过8个字节对齐

gflags.exe /p /enable test.exe /full

// 禁用越界检查

gflags.exe /p /disable test.exe /full

// 一个字节的越界都不行

gflags.exe /p /enable test.exe /full /unaligned

 

 

页堆能处理的错误类型:

 

错误类型 正常页堆 整页堆
堆句柄无效 立即发现 立即发现
堆内存块指针无效 立即发现 立即发现
多线程访问堆不同步 立即发现 立即发现
假设重新分配返回相同地址(realloc) 90%内存释放后发现 90%立即发现
内存块重复释放 90%立即发现 90%立即发现
访问已释放的内存块 90%在实际释放后发现 90%立即发现
访问块结尾之后的内容 在释放后发现 立即发现
访问块开始之前的内容 在释放后发现 立即发现

发表评论

电子邮件地址不会被公开。 必填项已用*标注