C/C++什么是内存泄露,内存泄露如何避免

C/C++什么是内存泄露,内存泄露如何避免?

1. 内存溢出

  内存溢出 OOM (out of memory),是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个int,但给它存了long才能存下的数,那就是内存溢出。

2. 内存泄漏

  内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。最终的结果就是导致OOM。
  内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。

3. 造成内存泄露常见的三种情况

1,指针重新赋值
2,错误的内存释放
3,返回值的不正确处理

3.1 指针重新赋值

如下代码:

char * p = (char *)malloc(10);
char * np = (char *)malloc(10);

 
 
  • 1
  • 2

其中,指针变量 p 和 np 分别被分配了 10 个字节的内存。
在这里插入图片描述如果程序需要执行如下赋值语句:

p=np;

 
 
  • 1

这时候,指针变量 p 被 np 指针重新赋值,其结果是 p 以前所指向的内存位置变成了孤立的内存。它无法释放,因为没有指向该位置的引用,从而导致 10 字节的内存泄漏。
在这里插入图片描述因此,在对指针赋值前,一定确保内存位置不会变为孤立的。

类似的情况,连续重复new的情况也是类似:

 int *p = new int; 
 p = new int...;//错误

 
 
  • 1
  • 2

3.2 错误的内存释放

假设有一个指针变量 p,它指向一个 10 字节的内存位置。该内存位置的第三个字节又指向某个动态分配的 10 字节的内存位置。
在这里插入图片描述如果程序需要执行如下赋值语句时:

free(p);

 
 
  • 1

很显然,如果通过调用 free 来释放指针 p,则 np 指针也会因此而变得无效。np 以前所指向的内存位置也无法释放,因为已经没有指向该位置的指针。换句话说,np 所指向的内存位置变为孤立的,从而导致内存泄漏。
因此,每当释放结构化的元素,而该元素又包含指向动态分配的内存位置的指针时,应首先遍历子内存位置(如本示例中的 np),并从那里开始释放,然后再遍历回父节点,如下面的代码所示:

free(p->np);
free(p);

 
 
  • 1
  • 2

3.3 返回值的不正确处理

有时候,某些函数会返回对动态分配的内存的引用,如下面的示例代码所示:

char *f(){
	return (char *)malloc(10);
}
void f1(){
	f();
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

函数 f1 中对 f 函数的调用并未处理该内存位置的返回地址,其结果将导致 f 函数所分配的 10 个字节的块丢失,并导致内存泄漏。
4) 在内存分配后忘记使用 free 进行释放

4. 如何避免内存泄露?

  • 确保没有在访问空指针。
  • 每个内存分配函数都应该有一个 free 函数与之对应,alloca 函数除外。
  • 每次分配内存之后都应该及时进行初始化,可以结合 memset 函数进行初始化,calloc 函数除外。
  • 每当向指针写入值时,都要确保对可用字节数和所写入的字节数进行交叉核对。
  • 在对指针赋值前,一定要确保没有内存位置会变为孤立的。
  • 每当释放结构化的元素(而该元素又包含指向动态分配的内存位置的指针)时,都应先遍历子内存位置并从那里开始释放,然后再遍历回父节点。
  • 始终正确处理返回动态分配的内存引用的函数返回值。

5. 内存泄露检测工具valgrind

这是一个linux下的内存泄露检测工具
内存泄露情况:
在这里插入图片描述
无内存泄露情况:
在这里插入图片描述

            转载于:https://blog.csdn.net/weixin_44718794/article/details/107071169#:~:text=%E2%80%83%E2%80%83%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%E6%98%AF%E6%8C%87%E4%BD%A0%E5%90%91%E7%B3%BB%E7%BB%9F%E7%94%B3%E8%AF%B7%E5%88%86%E9%85%8D%E5%86%85%E5%AD%98%E8%BF%9B%E8%A1%8C%E4%BD%BF%E7%94%A8%28new%29%EF%BC%8C%E5%8F%AF%E6%98%AF%E4%BD%BF%E7%94%A8%E5%AE%8C%E4%BA%86%E4%BB%A5%E5%90%8E%E5%8D%B4%E4%B8%8D%E5%BD%92%E8%BF%98%28delete%29%EF%BC%8C%E7%BB%93%E6%9E%9C%E4%BD%A0%E7%94%B3%E8%AF%B7%E5%88%B0%E7%9A%84%E9%82%A3%E5%9D%97%E5%86%85%E5%AD%98%E4%BD%A0%E8%87%AA%E5%B7%B1%E4%B9%9F%E4%B8%8D%E8%83%BD%E5%86%8D%E8%AE%BF%E9%97%AE%EF%BC%88%E4%B9%9F%E8%AE%B8%E4%BD%A0%E6%8A%8A%E5%AE%83%E7%9A%84%E5%9C%B0%E5%9D%80%E7%BB%99%E5%BC%84%E4%B8%A2%E4%BA%86%EF%BC%89%EF%BC%8C%E8%80%8C%E7%B3%BB%E7%BB%9F%E4%B9%9F%E4%B8%8D%E8%83%BD%E5%86%8D%E6%AC%A1%E5%B0%86%E5%AE%83%E5%88%86%E9%85%8D%E7%BB%99%E9%9C%80%E8%A6%81%E7%9A%84%E7%A8%8B%E5%BA%8F%E3%80%82,3.
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值