网络

教育改变生活

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 913|回复: 0
打印 上一主题 下一主题

【C语言】内存泄漏

[复制链接]

686

主题

693

帖子

3101

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3101
跳转到指定楼层
楼主
发表于 2024-12-9 12:59:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
大家都知道,在堆上分配的内存,如果不再使用了,就应该及时释放,以便后面其他地方可以重用。而在 C 语言中,内存管理器不会自动回收不再使用的内存。如果忘了释放不再使用的内存,这些内存就不能被重用了,这就造成了内存泄漏

内存泄漏几乎是很难避免的,不管是老手还是新手,都存在这个问题,甚至 Windows 与 Linux 这类系统软件也或多或少存在着内存泄漏。

也许对一般的应用软件来说,这个问题似乎不是那么突出与严重。一两处内存泄漏通常并不致于让程序崩溃,也不会带来逻辑上的错误,而且在进程退出时,系统会自动释放所有与该进程相关的内存(共享内存除外),所以内存泄漏的后果相对来说还是比较温和的。但是,量变会导致质变,一旦内存泄漏过多以致耗尽内存,后续内存分配将会失败,程序就可能因此而崩溃。

在常见情况下,内存泄漏的主要可见症状就是罪魁进程的速度减慢。原因是体积大的进程更有可能被系统换出,让别的进程运行,而且大的进程在换进换出时花费的时间也更多。即使泄漏的内存本身并不被引用,但它仍然可能存在于页面中(内容自然是垃圾),这样就增加了进程的工作页数量,降低了性能。

下面展示了一些导致内存泄漏的常见场景。
1) 指针重新赋值

看下面一段示例代码:
  • char * p = (char *)malloc(10);
  • char * np = (char *)malloc(10);


其中,指针变量 p 和 np 分别被分配了 10 个字节的内存,它们各自的内存如图 1 所示。


图 1 p 和 np 赋值前的内存


如果程序需要执行如下赋值语句:
  • p=np;


这时候,指针变量 p 被 np 指针重新赋值,其结果是 p 以前所指向的内存位置变成了孤立的内存,如图 2 所示。它无法释放,因为没有指向该位置的引用,从而导致 10 字节的内存泄漏。


图 2 p 和 np 赋值后的内存


因此,在对指针赋值前,一定确保内存位置不会变为孤立的。
2) 错误的内存释放


假设有一个指针变量 p,它指向一个 10 字节的内存位置。该内存位置的第三个字节又指向某个动态分配的 10 字节的内存位置,如图 3 所示。


图 3 p 所指向的内存


如果程序需要执行如下赋值语句时:
  • free(p);


很显然,如果通过调用 free 来释放指针 p,则 np 指针也会因此而变得无效。np 以前所指向的内存位置也无法释放,因为已经没有指向该位置的指针。换句话说,np 所指向的内存位置变为孤立的,从而导致内存泄漏。

因此,每当释放结构化的元素,而该元素又包含指向动态分配的内存位置的指针时,应首先遍历子内存位置(如本示例中的 np),并从那里开始释放,然后再遍历回父节点,如下面的代码所示:
  • free(p->np);
  • free(p);


3) 返回值的不正确处理


有时候,某些函数会返回对动态分配的内存的引用,如下面的示例代码所示:
  • char *f()
  • {
  •     return (char *)malloc(10);
  • }
  • void f1()
  • {
  •     f();
  • }


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


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


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

WEB前端

QQ|手机版|小黑屋|金桨网|助学堂  咨询请联系站长。

GMT+8, 2024-12-22 11:10 , Processed in 0.033254 second(s), 21 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表