[toc]
# 什么是内存泄漏
由于疏忽错误导致的程序未能释放已经不再使用的内存
- 比如指针丢失
- 引用丢失
- 上述两种情况下没有 free 或者 delete 释放内存
这样就算一次丢失可以忽略不计,但如果一直发生,一直叠加,就会导致整个系统越来越慢 常见得几种情况
- 由于疏忽或者错误失去了对内存的控制
- 堆内存泄漏,因为堆内存是用户控制的,如果使用不当,就会发生泄露
- 使用
malloc、calloc、realloc、new
等分配内存时,使用完后要调用相应的 free
或 delete
释放内存,否则这块内存就会造成内存泄漏
- 指针重新赋值
# 例子
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)++; cout<<"count is :" << *p_count <<endl; }
~A(){ (*p_count)--; cout<<"count is : "<<*p_count <<endl;
if(*p_count == 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; cout<<"ex1.p = "<<ex1.GetPointer() <<endl;
}
int main(){ fun(); return 0; }
|
# 智能指针
智能指针是 C++ 中一进队内存泄漏封装好了的一个工具
# 内存泄漏检测工具
valgrind (Linux 专用,Tag 一下)