简单的Memory leak跟踪(一) DEBUG_NEW方案
前言
C++编码中Memory Leak是一个很讨厌却又挥之不去的话题,最近由于引入了GC,为了验证GC是否确实正常free了内存,于是先提供了一个内存分配的Tracer。
与分配器不同,分配器主要解决的是两个问题:
1、性能,池式分配往往能提供比直接Virtual Allocation快得多的效能。据说这一原则在Vista后无效了,因为微软修改了VA的实现机制,只是听说,没有实际测试过。
2、碎片,避免大量散内存分配冲散了本身连续的内存,导致后面内存因为没有连续区块而分配不出来。
我们的跟踪器Tracer主要是想解决一个问题,就是啥时候分了内存,啥时候删的,程序退出时删除掉没。
基本上,这个主题之前也有很多前辈都写过了,这里也没有超越前辈们的什么方案,只是自己做这个模块时的心得和理解。
这个问题有两个比较成型的方案,一个就是MFC的DEBUG_NEW方案,MAX SDK用的也是这个方案。
其实原理很简单,我们只要能获取到当前语句的文件名和行号,然后new的时候,我们让我们的Tracer记录一下当前的地址,并与文件名和行号绑定,然后,delete的时候,按照地址来去掉这条记录即可。
实现起来如何实现呢?
这个问题无非是要解决两个问题,首先,new这个东西,我们需要接管下来,接管下来后才能记录我们自己的信息。
C++的operator new是可以有不同形式的重载的,比如:
?方不方便,后面还会继续展开,敬请期待。
补充1:提供新格式的operator new后,为何要提供相应的operator delete呢?因为C++标准规定,object的构造是可以有异常的,如果构造有异常,那么当前object就应该被回收。如果你对这个object的new使用了自定义格式,那么在构造函数异常时,C++回收object也会使用对应自定义格式的delete,所以相应的operator delete一定要提供,否则这种情况下内存就不会回收了。\
但如果一切正常,手动调用delete时,调用的是哪个delete呢?答案是标准的delete:void operator delete(void* InPtr);
另外,new 和 operator new 不是一回事儿?是的,new是C++关键字,new做的事情是什么呢?1,调用对应形式的operator new,分配内存。2,调用placement new,也就是对象的构造函数,构造对象。也就是new有两步,第一步是operator new,operator new只管分配内存,不管别的。