C++内存泄露几种常见原因

13 篇文章 0 订阅

在cpp编程中,产生内存泄漏的主要原因是利用malloc或者new等分配内存的方式申请内存后,由于主观或者客观原因没有进行释放,导致申请的内存区域没有及时得到释放导致的。

下面对几种常见/特殊的情况进行简单记录。

1. 析构函数中未匹配地释放内存

2. 基类的析构函数没有设为虚函数,

由于基类的析构函数不是虚函数,在实现多态时,通过delete删除指向派生类的基类指针时,派生类的析构函数被覆盖无法调用,而是调用的基类的析构函数,导致派生类对象无法被释放,导致内存泄漏。

3. 关于指针数组释放

对于二维数组,利用指针的定义区别如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

int``(*a)[N]=``new``int``[M][N];??``//N必须为已知

//对应内存释放为

delete``[] a;

int``**b=``new``int``*[M];

for``(``int``i=0;i<M;i++)

{

????????``b[i]=``new``int``[N];?

}

//对应内存释放为

for``(``int``i=0;i<M;i++)

{

????????``delete``[] b[j];?????

}

delete``[] b;

delete[]不光需要释放对象的空间,还要释放其中的每个指针,否则释放的不彻底。

4. 拷贝构造函数和运算符重载的问题

当类缺少拷贝构造函数时,可能造成内存泄露问题。具体场景主要是当一个类中有指针成员,但是没有编写拷贝构造函数时,系统将会调用默认构造函数,采用值传递的方式。这种隐式传递的方式容易造成两个对象同时具有指向同一个地址的指针成员。因此在释放对象的时候,第一个对象能够正常释放,而第二个对象的释放将会释放相同的内存,这是一种错误的做法,可能会导致堆的崩溃。因此当类中含有指针成员时,应当显示地重写构造函数和重载运算符,以保证深拷贝的发生。

5.shared_ptr的循环引用问题

身为智能指针的shared_ptr也可能存在内存泄露问题。如下面情况

当类A和类B中分别含有类型为对方的智能指针,并且在各自创建实例a和b后,对实例a/b中的智能指针传入b/a进行了赋值。那么在离开作用域后,实例a和实例b中的智能指针引用计数都是1,但是都在等待对方释放后才能释放,这种情况便造成了循环引用的问题。具体代码实例如下:

class ClassA {
public:
  …
void setInnerPtr(shared_ptr pB) {
p = pB;
}
private:
shared_ptr p;
};

class ClassB {
public:
  …
void setInnerPtr(shared_ptr pA) {
p = pA;
}

private:
shared_ptr p;
};
int main()
{
  shared_ptr pA = make_shared();
  shared_ptr pB = make_shared();

pA->setInnerPtr(pB);
  pB->setInnerPtr(pA);
  …
}

这种情况可以引入weak_ptr来解决,在ClassA和ClassB的声明中用weak_ptr代替shared_ptr后,不会产生引用计数,因此不会产生循环引用的问题。

其他会造成野指针的情况:

1)指针变量没有被初始化(如果值不定,可以初始化为NULL)

2)指针所指内存被释放后,没有置为NULL。

3)指针操作超越了变量的作用范围,比如返回指向栈内存的指针就是野指针。

总结

写到这里也结束了,在文章最后放上一个小小的福利,以下为小编自己在学习过程中整理出的一个关于 java开发 的学习思路及方向。从事互联网开发,最主要的是要学好技术,而学习技术是一条慢长而艰苦的道路,不能靠一时激情,也不是熬几天几夜就能学好的,必须养成平时努力学习的习惯,更加需要准确的学习方向达到有效的学习效果。

由于内容较多就只放上一个大概的大纲,需要更及详细的学习思维导图的 点击我的Gitee获取
还有 高级java全套视频教程 java进阶架构师 视频+资料+代码+面试题!

全方面的java进阶实践技术资料,并且还有技术大牛一起讨论交流解决问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值