每日一问10:C++中的内存泄漏
每日一问10:内存泄漏
内存泄漏是什么
内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。内存泄漏不是指内存在物理上的消失,而是指失去了对该段内存的控制,因而造成了内存的浪费。内存泄漏仅仅指程序在运行时,程序退出时,OS将回收所有的资源。
可能产生内存泄漏的地方
内存泄漏产生的原因基本都是,申请的资源没有正确的释放。
1.程序new申请的内存没有及时使用delete释放掉 ,导致内存泄漏。举一个比较极端的例子:
#include <iostream>
#include <new.h>
using namespace std;
void out_of_memory()
{
cout << "ERROR:内存已耗尽!" << endl;
}
int main()
{
set_new_handler(out_of_memory);//set_new_handler函数的作用是设置new_p(这里是out_of_memory)指向的函数为
//new操作或new[]操作失败时调用的处理函数。
while(1)
new int[1000];
return 0;
}
这段代码会一直先堆区申请内存而不释放,导致系统内存耗尽,随后申请内存失败,并调用out_of_memory,输出内存已耗尽。
2.使用new创建了一组对象数组,内存回收的时候却只调用了delete而非delete []来处理,导致只有对象数组的第一个对象的析构函数得到执行并回收了内存,而数组的其他对象的内存得不到回收,导致内存泄露。
class Object1
{
int a;
int b;
};
int main() {
Object1* arry1 = new Object1[100];//创建包含100个Object1的对象数组arry1并返回数组首地址;
Object1* arry2 = new Object1[100];//创建包含100个Object1的对象数组arry2并返回数组首地址;
delete []arry1;//回收了数组arry1里的所有对象动态创建时占用的内存空间;
delete arry2;//回收了数组arry2里的第一个对象动态创建时占用的内存空间,导致其他99个对象的内存空间泄露;
cout << "Press any key to continue... ..." << endl;
getchar();
return 0;
}
3.除了上面介绍的堆内存泄漏(Heap leak),在使用系统资源没有正常释放,也导致系统资源释放。如使用套接字、文件描述符、管道等系统资源后,没有使用对应的函数释放掉,导致系统资源的浪费,严重可导致系统效能减少,系统执行不稳定。
4.没有将基类的析构函数定义为虚函数。当基类指针指向子类对象时,如果基类的析构函数不是virtual,那么子类的析构函数将不会被调用,子类的资源没有正确是释放,因此造成内存泄露。
5.对于对象数组,只释放了数组,却没有逐个释放数组中的对象。
6.使用形如int a = *new int(1);的代码,这句代码在C++中是不会报错的,意为使用new申请一个int对象,初始化为0,并将0值赋给变量a。
总结
大部分内存泄漏,都是在编程过程中没有正确使用导致的,使用STL智能指针以及各种容器类可以很大程度上避免这种内存泄漏。对于系统资源的释放使用RALL也可以很大程度避免。
参考博客:
1. C++造成内存泄漏的原因汇总:_盖伊福克斯-CSDN博客_c++内存泄漏