APP下载

C++语言中悬挂指针的研究与应用

2016-11-02徐萍

电脑知识与技术 2016年23期
关键词:运算符指针内存

徐萍

摘要:C++悬挂指针是指那些不能正确指向合法的指针,该指针会使系统发生不可估计的后果。该文研究了国内外研究现状,从而介绍了Apace、谷歌等著名软件都存在C++悬挂指针,进一步分析了C++悬挂指针出现的类型有:指针未初始、指针对象不存在及指针释放出现问题,并提出了悬挂指针的解决方法。

关键词:C++;悬挂指针;内存泄漏

中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2016)23-0065-02

C++语言是一门极其复杂的语言,许多程序员在使用C++语言指针编写程序时。由于操作不当,往往会出现动态内存问题,比如悬挂指针。悬挂指针是一种常见的Bug,而且不容易发现。潜在的悬挂指针危害极其严重,会导致内存溢出等安全问题。著名的开源服务器Apace就存在一个悬挂指针漏洞,该漏洞存在于Apace mod_isapi模块中,在使用Apace服务器时会出现内存溢出问题。BLee[1]统计了谷歌浏览器从2011年到2013年之间出现C++悬挂指针的漏洞如表1所示。

由此可见,针对C++悬挂指针的危害,进行C++悬挂指针的研究是非常重要的。

1 C++语言悬挂指针故障分析

悬挂指针是指针指向释放内存后的指针,是野指针的一类。C++内存分配方法是主要有堆、栈、自由存储区、全局/静态存储区以及常见存储区。下面对C++语言中悬挂指针故障进行分析。

1.1 使用未初始的指针

首先看例1代码。该程序能够通过编译,但是在运行时会出现问题。这是因为char*name定义了变量但没有指针进行初始化,因而会出现悬挂指针。

1.2 指针所指的对象消失

查看代码如例2所示,运行程序结果不是0.0。这是因为在C++中由于指针对象是有生命周期的,当一个对象生命周期结束指针就消失,变量my是存在于栈的局部空间中,离开变量后就立即被释放,因此输出的结果是未知的。

1.3 直至释放后位置空

在C++中内存释放和分配有:malloc、free、delete及new等运算符。运算符new 、malloc是在堆上进行内存分配,同时将分配地址的首地址返回给指针。运算符delete、free是将分配的地址释放。如果程序使用了new、malloc没有释放地址,该地址仍然存在,该指针便成为悬挂指针,程序在使用指针时会发生内存泄漏。例3为new运算产生的悬挂指针,例4为malloc运算产生的悬挂指针。

2 C++语言悬挂指针解决方法

为解决C++语言产生悬挂指针问题,国内外学者对其进行了研究。孙涛[2]提出了一种悬挂指针故障的静态检测方法。该方法研究了函数间、函数依赖关系、函数摘要及故障检测算法具体操作。函数间主要用于代码未运行时,查看代码调用情况。函数依赖关系是若函数fun1()调用了函数fun2(),,则可将函数fun1()依赖于函数fun2()如图1所示。

函数摘要是对函数内容的抽象描述,在函数检测中如果检测到有函数调用,程序可以在内容中提取调用函数信息,这样提高了分析效率,故障检测算法是在函数摘要基础上进行故障检测。

SC Gupta[3]开发了一款悬挂指针及内存泄漏检测软件。该软件工作原理是当程序分配和释放内存时,软件会记录指针在内存中的信息比如指针位置及状态,当程序在指针内写入新的地址时,同时软件会读取指针引用的地址,与原来指针信息进行对比以确定悬挂指针位置及内存泄漏位置。在该过程中有多个节点平衡二叉树,其中节点代表了堆或栈记录,该软件工作流程如图2所示。

Dhurjati D[4]为了检测悬挂指针提出了一种新的技术用于检测运行时悬挂指针。该技术使用一个新的虚拟页分配的程序和依靠页保护机制来检查悬挂指针访问。一是利用新的虚拟页面程序进行分配,并使之映射到相同物理页面的原始分配器上。这种做法中原始程序和物理内存基本是一样的,且能够有效地使悬挂指针的检测能力得以保留。二是利用自动池实现对之前开发编译器的改造利用,并利用虚拟页面解决虚拟地址空间耗尽这一问题。通过实验得到改进技术后的Unix服务器开销小于4%,远低于未改进的Unix。

Nagarakatte S[5]为了解决悬挂指针内存分配与释放问题,提出了一种解决方案。该方案是以编译器执行时间的安全(CETS:compiler enforced temporal safety for C)为出发点,CETS将维护的对象进行标识,结合现有的检测方法CETS保持了指针在内存分布局部的完整性,同时检查该对象是否被引用到指针中。结果表明:使用CETS方法能够提高悬挂指针检测效率,安全性也增加。

3 结束语

即便是经验丰富的C++程序员在编写指针程序时,也会出现悬挂指针这一隐蔽Bug。在使用指针时要考虑到指定初始化及赋NULL值,在使用malloc、delete 及malloc、free等运算符时应该将分配的指针指向NULL。开发人员在编写程序时,如果能够使用变量引用来实现某一功能时就尽量不使用指针这一变量,这样可以避免悬挂指针问题。

参考文献:

[1] Lee B, Song C, Jang Y, et al. Preventing Use-after-free with Dangling Pointers Nullification[C]// Network and Distributed System Security Symposium. 2015.

[2] 孙涛, 宫云战, 金大海. 一种悬挂指针故障的静态检测方法[J]. 计算机研究与发展, 2010(S1): 69-73.

[3] Gupta S C. Detecting dangling pointers and memory leaks within software: US, US 8245209 B2[P]. 2012.

[4] Dhurjati D, Adve V. Efficiently Detecting All Dangling Pointer Uses in Production Servers[C]// International Conference on Dependable Systems and Networks. IEEE, 2006:269-280.

[5] Nagarakatte S, Zhao J, Martin M M K, et al. CETS: compiler enforced temporal safety for C[J]. Acm Sigplan Notices, 2010, 45(8): 31-40.

猜你喜欢

运算符指针内存
老祖传授基本运算符
外部高速缓存与非易失内存结合的混合内存体系结构特性评测
用手机插头的思路学习布尔运算符
“春夏秋冬”的内存
基于改进Hough变换和BP网络的指针仪表识别
ARM Cortex—MO/MO+单片机的指针变量替换方法
基于内存的地理信息访问技术
表达式求值及符号推导
C++中运算符的重载应用