一、开辟的内存没有释放(堆内存泄漏)
C++程序在执行时,将内存大方向划分为4个区域:
代码区:存放函数体的二进制代码,由操作系统进行管理的;
全局区:存放全局变量和静态变量以及常量;
栈区:由编译器自动分配释放, 存放函数的参数值, 局部变量等;
堆区:由程序员分配和释放, 若程序员不释放, 程序结束时由操作系统回收。
通过malloc、new等从堆中分配出来的内存,在使用完成后必须通过调用对应的 free、delete删掉。如果程序的设计的错误导致这部分内存没有被释放,那么此后这块内存将不会被使⽤,就会产⽣泄漏,其中new[],需要用delete[] 删除。
二、系统资源泄漏
主要指程序使⽤系统分配的资源⽐如handle、socket等没有使⽤相应的函数释放掉,导致系统资源的浪费,严重可导致系统效能降低,系统运⾏不稳定。
二、基类析构函数未声明为虚函数
首先定义一个基类和一个派生类,此时基类的析构函数未声明为虚函数。
class Human
{
public:
Human()
{
cout << "执行了Human::Human()" << endl;
};
~Human()
{
cout << "执行了Human::~Human()" << endl;
}
};
class Men : public Human
{
public:
Men()
{
cout << "执行了Men::Men()" << endl;
}
~Men()
{
cout << "执行了Men::~Men()" << endl;
}
};
Human* phuman = new Men;
delete phuman; //没有执行子类的析构函数
此时使用delete来释放内存时,发现没有调用派生类的析构函数,只调用了基类的析构函数。
当派⽣类对象中有内存需要回收时,如果析构函数不是虚函数,不会触发动态绑定,只会调⽤基类析构函数,导致派⽣类资源⽆法释放,造成内存泄漏。 虚函数机制是实现多态的关键。多态允许我们通过基类指针或引用来调用派生类中重写的函数,这样在运行时可以确定调用哪个函数。当使用基类指针删除派生类对象时,C++运行时会检查对象的实际类型(即派生类类型),并找到对应的虚函数表。然后,它会调用虚函数表中指向析构函数的指针。
在public继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员。如果想要用基类对非继承部分进行操作,则需要把基类的这个函数定义为虚函数。
在基类的析构函数前添加virtual将其声明为虚析构函数,即可解决上述问题。
class Human
{
public:
Human()
{
cout << "执行了Human::Human()" << endl;
};
virtual ~Human()
{
cout << "执行了Human::~Human()" << endl;
}
};
成功调用了派生类的析构函数。