为什么重复free()比内存泄漏危害更大
创始人
2024-07-30 01:00:45
0

C程序设计中,内存操作相关的错误可以说是最常见,同时也是非常隐蔽的一类错误。这类错误往往导致程序莫名其妙地崩溃、耗尽系统资源,或是形成严重的安全弱点。

在 FreeBSD,以及多数其他 BSD 派生的系统中,重复 free() 在默认情况下都会导致 C 函数库调用 abort() 终止程序。除了 malloc(3) 函数族本身的设计之外,这也是一项非常重要的安全特性。与此相反,包括 *BSD 在内的多数系统的 C 函数库并不对堆进行审计,也就是说,从 API 设计者的观点来看,内存泄漏并不被认为是非常严重的程序设计问题。

为什么会有这样的区别呢?事实上,内存泄漏同样可以导致比较严重的问题,例如响应速度变慢、进程由于占用的资源太多而被 OS 杀掉导致 DoS 等等。为了回答这个问题,我们来观察一下两种问题出现的场景。

内存泄漏 是指这样一种场景:程序分配了一块内存,但已经不再持有引用这块内存的对象(通常是指针)。从 OS 的角度,它知道进程持有的内存数量;然而,从进程的角度,它可能并不完全知道自己持有哪些内存。

换言之,内存泄漏就是通过遍历进程内所有可以从栈上,或以静态变量形式存于堆上的指针及其后继,无法到达所有全部已分配内存的情形。

如果程序不存在其他问题(例如缓冲区溢出),此时程序访问内存时,任何时候都不会在无意中覆写超出范围的数据。即,将数据覆写到程序其他部分保存数据的内存单元。

而 重复释放 则指这样一种场景:程序分配一块内存之后,经过使用将这块内存释放,但并没有将指向这块内存的所有指针抹零或回收,并在其他部分再次将指向同一块内存单元的指针交给内存分配器去进行释放操作。这种情况下,我们可以断言:

1、程序逻辑并不清楚这块内存已经被释放;

2、有理由相信,对这块内存进行的写操作,可能已经影响了程序其他部分的行为,因为这块内存可能已经分配作为其他用途。
因此,这应被看作立即停止程序运行的一项致命错误,因为程序行为已经出现了异常,而C函数库拥有的信息不足以纠正这种异常行为,而另一方面,程序可能已经发生了堆缓冲区溢出。

为了削弱这类问题带来的实质性安全影响,现代的内存分配器往往会将尺寸接近的内存块放在一起(这样做还能够抑制内存碎片的产生,并提高CPU的数据缓存命中率,因为通常程序会倾向于一次性地访问相近的内存结构)。

从而能够在一定程度上减轻由于向已经释放的内存块继续写数据导致的损害(因为这些内存很可能被分配给同样的数据结构,这类写操作的危害往往会低于向其他类型的数据结构写数据,特别是当这些数据中包含一部分用户输入的时候)。

当然,彻底消除这类问题,需要为程序设计语言增加一些新的基础设施(例如强类型、托管内存等)。现代程序设计语言如Java、Python和.net系列等,都采用了避免这类问题的措施。然而,也正因为如此,通过这些语言入门并准备撰写 C 程序的开发人员就更需要注意这类问题。

【编辑推荐】

  1. C++三则 如无必要 勿增虚函数
  2. 关于C++虚函数那点破事
  3. 浅谈怎样加快C++代码的编译速度
  4. 善于从bug中分析问题也是一种能力
  5. 页面制作也是一门艺术

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...