1、定义
wikipedia中这样定义内存泄漏:在计算机科学中,内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。
简单来说:内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。
2、危害
只发生一次的小的内存泄漏可能不会被注意,但泄漏大量内存的程序或泄漏日益增多的程序可能会表现出各种征兆:从性能不良(并且逐渐降低)到内存完全用尽。 更糟的是,泄漏的程序可能会用掉太多内存,以致另一个程序失败,而使用户无从查找问题的真正根源。 此外,即使无害的内存泄漏也可能是其他问题的征兆。
在以下情況,内存泄漏导致较严重的后果:
3、原因和场景
对于C++的内存泄漏,总结一句话:就是new出来的内存没有通过delete合理的释放掉!
char * FunA()
{
char *p = new char;
return p;
}
void FunErrorB()
{
char *b = FunA();
//忘记delete p
}
Void FunErrorA()
{
Char *p = new char[10];
Delete p;//错误
}
#include ;
using namespace std;
class T
{
public:
T()
{
cout <<"构造T"<<endl;
}
~T()
{
cout <<"析构T"<<endl;
}
};
int main()
{
int NUM = 3;
T *p1 = new T[NUM];
cout<<p1<<endl;
delete[] p1;//正确释放语句
cout<<"释放了p1空间"<<endl;
T *p2 = new T[NUM];
cout<<p2<<endl;
delete[] p2;//正确释放语句
cout<<"释放了p2空间"<<endl;
system("pause");
return 0;
}
指向对象的指针数组是指:数组中存放的是指向对象的指针,不仅要释放每个对象的空间,还要释放每个指针的空间,delete []p只是释放了每个指针
,但是并没有释放对象的空间,正确的做法,是通过一个循环,将每个对象释放了,然后再把指针释放了。
4、delete掉一个void*类型的指针,导致没有调用到对象的析构函数,析构的所有清理工作都没有去执行从而导致内存的泄露;
class Object {
private:
void* data;
const int size;
const char id;
public:
Object(int sz, char c):size(sz), id(c){
data = new char[size];
cout << "Object() " << id << " size = " << size << endl;
}
~Object(){
cout << "~Object() " << id << endl;
delete []data;
}
};
int main() {
Object* a = new Object(10, 'A');//Object*指针指向一个Object对象;
void* b = new Object(20, 'B');//void*指针指向一个Object对象;
delete a;//执行delete,编译器自动调用析构函数;
delete b;//执行delete,编译器不会调用析构函数,导致data占用内存没有得到回收;
cout << "Press any key to continue... ..." << endl;
getchar();
return 0;
}
通常来说,一个线程的栈内存是有限的,通常来说是 8M 左右(取决于运行的环境)。栈上的内存通常是由编译器来自动管理的。当在栈上分配一个新的变量时,或进入一个函数时,栈的指针会下移,相当于在栈上分配了一块内存。我们把一个变量分配在栈上,也就是利用了栈上的内存空间。当这个变量的生命周期结束时,栈的指针会上移,相同于回收了内存。
由于栈上的内存的分配和回收都是由编译器控制的,所以在栈上是不会发生内存泄露的,只会发生栈溢出(Stack Overflow),也就是分配的空间超过了规定的栈大小。
而堆上的内存是由程序直接控制的,程序可以通过 malloc/free 或 new/delete 来分配和回收内存,如果程序中通过 malloc/new 分配了一块内存,但忘记使用 free/delete 来回收内存,就发生了内存泄露。
具体相关方法:
RAII
对象中,当它超出范围时释放内存。RAII在构造函数中分配内存并在析构函数中释放内存,这样当变量离开当前范围时,内存就可以被释放。(注:RAII资源获取即初始化,也就是说在构造函数中申请分配资源,在析构函数中释放资源)
C++ 如何避免内存泄漏
1、https://zhuanlan.zhihu.com/p/51898119
2、https://blog.csdn.net/invisible_sky/article/details/78205461