重载new和delete来检测内存泄漏

  1. 简述

内存泄漏属于资源泄漏的一种,百度百科将内存泄漏分为四种:常发性内存泄漏、偶发性内存泄漏、一次性内存泄漏和隐式内存泄漏。

常发性指:内存泄漏的代码会被多次执行到。偶发性指:内存泄漏的代码只有在特定的条件下才会执行到。一次性指:内存泄漏的代码只会被执行到一次。隐式指:程序在运行中不断的开辟内存,知道程序结束时才释放内存,本质上虽然没有内存泄漏,但是如果这个程序在连续运行很长时间,会耗尽所有内存,导致系统崩溃。

下面首先介绍内存检测的基本原理,然后给出代码样例,最后说明针对四种内存泄漏进行检测的想法。

  1. 基本原理

内存泄漏就是new出来的内存没有通过delete合理的释放掉。new和delete这两个函数就是关键点。可以重载new和delete,每次new中开辟一块内存就用链表把这个内存的信息保存下来,每次用delete删除一块内存就从链表中删除这块内存的记录。

3. 代码样例
1#include<iostream>

2usingnamespacestd;

3//---------------------------------------------------------------

4//内存记录

5//---------------------------------------------------------------

6classMemInfo {

7private:

8voidptr;

9constchar
file;

10unsignedintline;

11MemInfolink;

12friendclassMemStack;

13};

14//---------------------------------------------------------------

15//内存记录栈

16//---------------------------------------------------------------

17classMemStack {

18private:

19MemInfo
head;

20public:

21MemStack():head(NULL) { }

22~MemStack() {

23MemInfotmp;

24while(head!=NULL) {

25free(head->ptr);//释放泄漏的内存

26tmp=head->link;

27free(head);

28head=tmp;

29}

30}

31voidInsert(void
ptr,constcharfile, unsignedintline) {

32MemInfo
node=(MemInfo)malloc(sizeof(MemInfo));

33node->ptr=ptr; node->file=file; node->line=line;

34node->link=head; head=node;

35}

36voidDelete(void
ptr) {

37MemInfonode=head;

38MemInfo
pre=NULL;

39while(node!=NULL&&node->ptr!=ptr) {

40pre=node;

41node=node->link;

42}

43if(node==NULL)

44cout<<"删除一个没有开辟的内存"<<endl;

45else{

46if(pre==NULL)//删除的是head

47head=node->link;

48else

49pre->link=node->link;

50free(node);

51}

52}

53voidPrint() {

54if(head==NULL) {

55cout<<"内存都释放掉了"<<endl;

56return;

57}

58cout<<"有内存泄露出现"<<endl;

59MemInfonode=head;

60while(node!=NULL) {

61cout<<"文件名:"<<node->file<<","<<"行数:"<<node->line<<","

62<<"地址:"<<node->ptr<<endl;

63node=node->link;

64}

65}

66};

67//---------------------------------------------------------------

68//全局对象 mem_stack记录开辟的内存

69//---------------------------------------------------------------

70MemStack mem_stack;

71//---------------------------------------------------------------

72//重载new,new[],delete,delete[]

73//---------------------------------------------------------------

74void
operatornew(size_t size,constcharfile, unsignedintline) {

75void
ptr=malloc(size);

76mem_stack.Insert(ptr, file, line);

77returnptr;

78}

79void*operatornew>

4. 代码说明

4.1 关于new的参数问题。

对于new int,编译器会解释为new(sizeof(int)),对于new int[5],编译器会解释为new(sizeof(int)*5)。因此使用宏定义预编译后,new int就变为new (FILE,LINE) int,编译器会解释为new(sizeof(int), FILE,LINE)。

4.2 关于MemStack

MemStack内部也是一个链表结构,注意内部实现不能使用new和delete,只能使用malloc和free来实现链表,因为待测代码中的重载new和delete中调用了MemStack的insert和delete函数,如果insert和delete函数也调用重载后的new和delete的话,会构成死循环的,所以直接使用free和malloc比较好。

MemStack中的析构函数,会释放掉泄漏掉的内存。

5. 使用思考

对于常发性和一次性的内存泄漏代码,直接放入测试就好了。对于偶发性的内存泄漏代码,只要满足特定条件,那么也就转化为常发性或者一次性的内存泄漏了。

对于隐式内存泄漏,由于程序是在很长一段时间之后导致内存耗尽,我们需要长时间观察,每隔一段时间比较一下内存的使用量,如果在一个较长的时间内,内存使用量持续增加,那么可以考虑是内存泄漏。不过调试起来可能会比较麻烦,还是需要重新审视程序设计的。

  1. 参考

百度百科_内存泄漏:介绍内存泄漏的基本分类。

http://baike.baidu.com/view/714962.htm

如何检查内存泄漏-重载new和delete:十分生动的说明。

http://www.cppblog.com/dawnbreak/articles/76223.html

一个跨平台的C++内存泄漏检测器:十分专业化的讲解和实现。

http://www.ibm.com/developerworks/cn/linux/l-mleak2/index.html
原文链接: https://www.cnblogs.com/pangxiaodong/archive/2011/08/29/2158136.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/31402

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 上午8:40
下一篇 2023年2月8日 上午8:41

相关推荐