VC中内存泄露的诊断

我以前的编程风格就是:闷头苦干,想到什么做什么,总是希望能够尽快地看到运行结果。这带来的直接后果是,很多煞费苦心写出来的代码,由于整体设计上考虑欠周道,必须大动手术,甚至重写和删除,这实在是一种浪费。所以我体会到:良好的设计才是软件开发的王道。

别说设计,就是代码工作本身也应该循序渐进,该停下来的时候必须停下来,好好的思考一下,整理一下。前段时间写了大量代码,由于浮躁的心态,却懒于整理,导致出现大量的内存泄露。尽管在现阶段,我非常清楚这些泄露的来源,但是一段时间以后呢,也许连代码怎么写出来的我都忘了,难道到时候又去花大量时间研究自己写的代码?就算是有文档辅助,这也比现在就纠正这些错误要困难得多。所以,绝不能让这些错误积累起来。

说干就干,一天时间,终于搞定了。大部分的内存泄露还是很好找的,但是还是需要有一些技巧的。

1. 使编译器自动指出泄露的内存被分配的代码在哪里。

在cpp文件中包含文件的后面

#define new DEBUG_NEW

DEBUG_NEW展开就是

#define DEBUG_NEW new(THIS_FILE, __LINE__)

很明显,有了这个定义,Output窗口在检测内存泄露的时候就可以指出内存是在哪里被new的。MFC使用的就是这个方法,但是这个方法有一个缺点,就是带参数的new没法使用了,比如placement new。这里不知道有没有解决办法。

在这里,可以多提一点,c++处理new的方式很巧妙,我们可以以任意参数重载operator new函数,但是所有的new都必须返回void*,并指定其为一块内存地址,然后编译器会在这块内存上调用所new对象的构造函数。比如,placement new 只有一个参数void*, 它所做的只是简单的返回这个参数而已.

2. 求助于dbgheap.c
如果cpp文件里没有定义DEBUG_NEW的话,从Output输出的信息还是可以看出端倪的。vs目录Vc7/crt/src/dbgheap.c里有一个函数_heap_alloc_dbg,在Debug版下new会调用该函数分配堆内存。在这个函数里设置条件断点,就可以找到内存分配之处了。这里比较有用的是lRequest,Output窗口输出的方括号里面的数字就是它了。

3. 分析内存数据
同事发现有些内存泄露lRequest是随机的,内存的地址也是随机的,如之奈何?我们可以分析内存的数据。如果泄露的内存是一个对象实例的话,一般其前四个字节会是虚函数表地址,由此就可以找到分配对象所属的类了。阿拉丁的同事还从泄露内存的数据第二个DWORD为01 00 00 00判断出这个1就是引用计数,肯定是有什么地方没有释放引用计数。

你可能感兴趣的:(C++,output,编译器,mfc,c++,文档,编程)