您的位置:首页 > 编程语言

不重载new操作符如何代码实现内存泄漏检测

2015-05-17 21:02 666 查看
  之前在win平台写代码的时候,对于内存泄漏的检查,是依赖于MS提供的一些机制,使用了诸如malloc_dbg,free_dbg这样的函数,内存泄漏的输出也是自动产生。由于工作的原因现在更多接触linux平台,就开始思考自己实现一个这样的东西,哪怕是简化版,或者能比较像样的达到目的也行。于是开始试着重载operate new

  刚开始还是挺顺利的,在operate new里面,用malloc函数去分配内存,在operate delete里面释放。然后我需要在分配内存的时候记录每次的信息,释放的时候移除对应的信息,以实现未释放信息的输出。那么我就打算用map。用自己实现的map可能隐蔽一些潜在问题,用std比较可靠。但是使用std并operate new的话,我有点犯怵,因为曾今win平台是遇到过问题的(当时是#define new new(__FILE__,__LINE__)产生了编译错误),当时的解决是把#include 这样的包含语句提前到operate new声明之前。而这次当我写好代码后,使用以前的经验也确实解决了编译问题,让使用std::map的代码完全‘看不见’operate new.但是运行起来后去发生崩溃。经过检查发现使用std::map的过程中并没有调用到operate new,但是却调用到了operate delete。虽然忽略了这种不匹配的情况,崩溃仍然发生。于是我觉得应该谨慎选择这种方式,可能存在难以预料的问题,毕竟这种做法涉及面太广,而且即便‘看不到’也产生了效用。

  经过一些搜索查阅,看到了这个文章《C++ 工程实践(2):不要重载全局 ::operator new() 》这里也较详细的为我们分析了用与不用operate new的情况以及可能引发的问题。为了不把事情越做越复杂,避免将来难以预料和控制的问题发生,不建议去重载new操作符。那么如何替代,我在看此文的过程中,并没发现作者提出好的办法,特别是new一个对象,如果用malloc,对构造函数的处理,是否对虚基类的使用有影响等,并没有提。所以我自己开始思考既能不改变原始内存分配工作方式,又能记录分配和释放操作。

  那么,最直接的想法就是,为何不在分配之前记下,释放之前移掉记录,而分配和释放动作按原本该有的方式去做,我不干涉呢?当然,实际写的过程中发现,分配内存之前没有分配得来的指针,无法记录,所以实际上是要分配内存之后记录下来。目前我的一个定义如下:(注意,因为压根没有测试,请慎重考虑是否套用)

[code]#ifndef MEMORY_NO_DEBUG

//@f.10.6 以下定义重新改成不干涉原始函数的方式。仅仅追踪量
#define JMalloc(size) jinAlloc(malloc(size),size,__FILE__,__LINE__)
#define JFree(pointer) jinFree(pointer);free(pointer)
#define JNew(type,...) (type*)jinAlloc(new type(__VA_ARGS__),sizeof(type),__FILE__,__LINE__)
#define JNewAry(type,count) (type*)jinAlloc(new type[count],sizeof(type)*count,__FILE__,__LINE__)
#define JDelete(pointer) jinFree(pointer);delete (pointer)
#define JDelAry(pointer) jinFree(pointer);delete[] (pointer)

void* jinAlloc(void *alloced, size_t size, const char *file, unsigned int line);
void jinFree(void *tobefree);

#else  // MEMORY_NO_DEBUG

#define JMalloc(l) malloc(l)
#define JFree(p) free(p)
#define JNew(type,...) new type(__VA_ARGS__)
#define JNewAry(type,count,...) new type[count]
//#define JNewAry(type,count,...) new type(__VA_ARGS__)[count]
#define JDelete(pointer) delete (pointer)
#define JDelAry(pointer) delete[] (pointer)

#endif // MEMORY_NO_DEBUG


于是使用的方式会是这样:

原本malloc(4) => JMalloc(4)

原本free(p) => JFree(p)

原本Student* s = new Student() => Student* s = JNew(Student)

原本char *buf = new char[100] => char *buf = JNewAry(char,100)

原本Student* s = new Student(“jin”,TRUE) => Student* s = JNew(Student,”jin”,TRUE)

原本delete[] buf => JDelAry(buf)

  再次提醒以上代码还处于开发阶段,完全没有测试,仅仅是编译通过加少量代码跑起。在jinAlloc和jinFree中使用map记录和移除记录(代码未贴出),在退出前将map中残留的记录输出就可以像模像样的做出内存泄漏检测了。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: