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.