[toc]

# 什么是内存泄漏

由于疏忽错误导致的程序未能释放已经不再使用的内存

  • 比如指针丢失
  • 引用丢失
  • 上述两种情况下没有 free 或者 delete 释放内存

这样就算一次丢失可以忽略不计,但如果一直发生,一直叠加,就会导致整个系统越来越慢 常见得几种情况

  • 由于疏忽或者错误失去了对内存的控制
  • 堆内存泄漏,因为堆内存是用户控制的,如果使用不当,就会发生泄露
  • 使用 malloc、calloc、realloc、new 等分配内存时,使用完后要调用相应的 freedelete 释放内存,否则这块内存就会造成内存泄漏
  • 指针重新赋值

# 例子

1
2
3
char *p = (char*)malloc(10);
char *p1 = (char *)malloc(10);
p = np;

p 指针原本指向的那块地址就失去了控制

# 怎么防止内存泄漏

# 内部封装的方式

即将内存的分配和释放封装到类中,在构造的时候申请内存,析构的时候释放内存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include<iostream>
#include<cstring>
using namespace std;

class A{
private:
char *p;
unsigned int p_size;
public:
A(unsigned int n=1){//构造函数中分配内存空间
p = new char[n];
p_size = n;
};
~A(){ //析构函数中释放内存空间
if(p!=NULL){
delete[] p; //删除字符数组
p = NULL; //防止出现野指针
}
};
char *GetPointer(){
return p;
};
};

void fun(){
A ex(100);
char *p = ex.GetPointer();
strcpy(p,"Test");
cout<<p<<endl;
}



int main(){
fun();
return 0;
}

但是,这样过并不是最佳的做法,在类的对象复制时,程序会出现同一块内存空间释放两次的情况. 比如下面这种情况

1
2
3
4
5
6
7
void fun1(){
A ex(100);
A ex1 = ex;
char *p = ex.GetPointer();
strcpy(p,"Test");
cout<<p<<endl;
}

对于 fun1 这个函数中定义的两个类的对象而言,离开函数的作用域时,会两次调用析构函数来释放空间,但这两个对象指向的是同一块内存空间,所以导致同一块内存被释放两次,可以通过增加计数机制来避免这种情况.

# 添加计数器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include<iostream>
#include<cstring>
using namespace std;

class A{
private:
char *p;
unsigned int p_size;
int *p_count; //计数变量
public:
A(unsigned int n=1){//构造函数中分配内存空间
p = new char[n];
p_size = n;
p_count = new int;
*p_count = 1;
cout<<"count is : "<<*p_count << endl;
};

A(const A &temp){
p = temp.p;
p_size = temp.p_size;
p_count = temp.p_count;
(*p_count)++; //复制时,计数变量+1
cout<<"count is :" << *p_count <<endl;
}

~A(){ //析构函数中释放内存空间
(*p_count)--;
cout<<"count is : "<<*p_count <<endl;

if(*p_count == 0){ //只有当计数变量为0的时候才会释放该块内存空间
cout<<"buf is deleted" << endl;
if(p!=NULL){
delete[] p; //删除字符数组
p = NULL; //防止出现野指针
if(p_count!=NULL){
delete p_count;
p_count = NULL;
}
}
}

};
char *GetPointer(){
return p;
};
};

void fun(){
A ex(100);
char *p = ex.GetPointer();
strcpy(p,"Test");
cout<<p<<endl;

A ex1 = ex; //此时计数变量会+1
cout<<"ex1.p = "<<ex1.GetPointer() <<endl;

}



int main(){
fun();
return 0;
}

# 智能指针

智能指针是 C++ 中一进队内存泄漏封装好了的一个工具

# 内存泄漏检测工具

valgrind (Linux 专用,Tag 一下)

更新于

请我喝[茶]~( ̄▽ ̄)~*

Solvarg 微信支付

微信支付

Solvarg 支付宝

支付宝

Solvarg 贝宝

贝宝