【论文阅读】Detecting Memory-Related Bugs by Tracking Heap Memory Management of C++ Smart Pointers(21ASE)


1、研究现状与背景

1.1 智能指针的发展及问题

C/C++语言中手动管理堆内存的方法容易出现错误且不方便,例如内存泄漏、空指针取消引用等。
新的C++标准(自C++11以来的连续版本)提供了智能指针机制(Smart printer):unique_ptr, shared_ptr, weak_ptr

下图展示了近年智能指针的运用趋势
在这里插入图片描
智能指针旨在防止内存泄漏错误
当智能指针超出范围时,可以自动释放分配给智能指针的内存块。此外,由于对析构函数的调用是由编译器调度的,智能指针还可以防止在释放错误后使用(use-after-free bugs)这些错误是由不正确调度的手动释放引起的
But,使用智能指针无法免疫所有类型的内存错误,如空智能指针解引用等。
本文定义由智能指针所引起的错误为:'Misuses of Smart Pointers (MisSP)

1.2 智能指针的使用

使用智能指针对象而不是原始指针来指向分配的内存。其次,在使用智能指针时,不需要手动释放托管内存。
example:
在这里插入图片描述
(1)RAII (Resource Acquisition Is Initialization) and Memory Ownership
在管理器对象初始化期间分配资源。它们的生存期通过管理器对象的变量绑定到相应的范围。因此,当资源不再可访问时,可以正确地释放资源。
手动分配的对象和数组将在销毁分配给它们的智能指针对象时自动解除分配。
当智能指针对象超出预期范围(例如,函数通常返回)或意外(例如,从该范围抛出异常)时,它将被销毁。
(2)Ownership of Heap Memory Blocks
堆内存块的所有权代表释放的责任,所有权可以在所有者之间转移,也可以由一组所有者共享。
当所有权由一个所有者唯一持有时,可以将其转让给其他所有者。这个唯一的所有者负责释放内存。
如果所有权是共享的,则不能转移,但可以由其中一个所有者释放,最后一个保留的所有者将释放内存。

1.3 智能指针的分类

表中显示的条目包括类名、引入该类的标准、ownership的类型、用户是否可以取消对智能指针的引用,以及是否支持管理动态数组(由运算符new[ ]分配)。
在这里插入图片描述

为了防止循环引用共享指针可能导致的内存泄漏,C++11标准中还引入了弱指针(weak_ptr)。
弱指针不是所有者,它们只引用由一组共享指针管理的所有权。因此,不能取消对它们的引用。要访问内存,需要将弱指针强制转换为共享指针。
由于自动指针已弃用且很少使用,因此本文主要讨论弱指针和两个所有者指针

1.4 MisSP 例子

example
在这里插入图片描述
Bug1: r为null时,*r则发生dereference a null smart printer
Bug2: On line 12, new[ ]申请的是char数组,而b的类型是char,类型mismatch。
Bug3:unique_ptr R被移动到函数HandleRequest的参数r。然后,运算符->将取消引用第14行上的空智能指针

1.5 MisSP分类

主要可以分为5类:
Dereference Null (DN).运算符箭头(->)、星号(*)和订阅([ ])解除对指针的引用。如果使用空智能指针调用这些运算符,将报告取消引用空错误。
Bad Assignment (BA).所有者智能指针管理的内存将始终被释放。因此,当智能指针指向不应释放的内存块(如堆栈内存等)时,将分配报告为错误的分配错误。
Type Mismatch ™.如果它与托管内存的分配器不匹配,我们将报告分配的类型不匹配错误。
Circular Reference (CR).共享指针无法使用垃圾收集器回收循环结构中的内存。当一个内存块环与智能指针连接时,我们将报告一个循环引用错误。
Unique Shared (US).参数p2只被解除引用,而不与其他对象或容器共享所有权。指针p1用于自动释放内存并满足调用函数使用的接口。在这种情况下,将报告指针p1和p2的唯一共享错误。
在这里插入图片描述

2. 论文贡献

现有分析器的shortcomings主要在2个方面:model and checker
Facing the shortcomings, we propose our models of smart pointers and checkers on MisSPs, 扩展了一个通用堆内存模型来处理C++内存管理操作,并与智能指针模型协作。定义了一组元操作来建模方法调用并记录智能指针对象的状态。此外,还基于从C++标准和著名编码规则中提取的五种错误模式定义了新的检查器。根据堆内存和智能指针的状态,使用这些检查器检查MisSP。

本文在Clang Static analyzer之上实现了一个名为Spelton的分析器,并使用手工基准和来自GitHub的9个开源C++项目对其进行评估。实验结果表明,本文的方法可以有效地检测MisSP。主要有以下3点贡献:
(1)通过一组元操作对智能指针的行为进行建模。堆内存块的状态也被扩展为由智能指针管理;
(2)实现了一个带有专门为5种提取的错误模式设计的检查器的分析器,以系统地扫描C++项目上的MisSP;
(3)发现和使用智能指针的建议也基于本文的统计数据和错误报告。

3. 论文提出的方法

workflow:
在这里插入图片描述
后文中,参数意义对照如下:
Mem->Memory
AM->Allocated memory
EM->captured memory from external context
Ptr->智能指针集合
Var->变量名集合
Λ->set of null pointer values
λ-> global null pointer constant

Malloc<->free
New<->delete
New[ ]<–>delete[ ]

将程序状态定义为一个三元组S=<M, P, Q>
M表示当前上下文中受监控的内存块集合
P表示所有跟踪的智能指针集合
Q表示内存到指针的映射

每一个内存块m∈M,定义为m=<id, at, st>
Id表示内存块的身份标识
At表示分配器类型at ∈ ADT
St表示内存块的状态st ∈ MemSt,MemSt = {Allocated, Captured, Escaped, Usable, Null, Freed, Bad}.

跟踪智能指针p ∈ P ,定义为p=<vn, dt, tm>
vn ∈ Var,作为唯一标识符
dt ∈ ADT,表示即将deallocate的类型
tm ∈ Mem,表示指向它的内存块

3.1 内存块状态转换建模

用函数DEL(t)表示相应的DEALLOCATE操作。
ALLDEL表示所有三种DEALLOCATE操作。
如果ma∈ AM由一组共享指针管理,其中一个指针被发送到未解释的函数或插入到STL容器中,操作RELINQUISH会将其状态更改为Escaped。
对于通过外部指针捕获的内存块(me∈ EM),其初始状态为“Captured”,其分配器类型设置为“any”。一方面,如果通过操作LOAD直接取消了对me的引用,我们将把它的状态修改为Usable。
如果使用操作CHECK检查其空值,则状态在then分支上将更改为Usable,而在else分支上更改为Null。
All the Allocated, Escaped and Usable memory blocks canbe deallocated.
These errors are mismatched memory management routines (Allocated and Escaped to Bad), use after free (Freed to Bad) and null pointer dereference (Null to Bad).
在这里插入图片描述

3.2 智能指针状态转移建模

(1)Owner smart pointer operations:
元操作meta-operations:set和unset
在这里插入图片描述

eg:Clear:对于唯一指针和最后一个活动共享指针,定义(3)用于取消分配托管内存块并将指针设置为空。而当清除一个空的智能指针或一组共享指针中的一个时,定义(4)可以取消分配该指针并保持内存不变。
在这里插入图片描述
(2)weak smart pointer operations:
由于它们不管理所有权并且不能取消引用,因此它们只有两个操作:CATCH和LOCK
CATCH操作:用于引用一组共享指针的所有权。由于弱指针不是托管内存块m的所有者,因此我们只重置该值,而不将指针添加到指针对象内存块Q[m]的所有者集。
LOCK操作:用于从引用的所有权创建新的共享指针。如果一个弱指针指向具有“已捕获”状态的内存块m,则将首先使用操作CHECK来确定其空值,并通过对Usable和Null分支的递归调用创建共享指针ps。
当m的状态为Allocated、Escaped或Usable时,创建的共享指针ps将共享m的所有权。
如果m不能取消引用,即释放、Null或错误时,将创建一个Null共享指针。当释放其内存块时,弱指针将过期。
在这里插入图片描述

3.3 工具工作原理example

在这里插入图片描述
第12行:checkers found that the last clause of the precondition, m1.at = Any ∨(m1.at ?= Any ∧m1.at = b.dt) is violated, where b.dt = Object and m1.at = Array,产生type mismatch bug
第13行:对std::move的函数调用将触发操作move(R,r),该操作将所有权从函数Entry的参数R移动到函数HandleRequest的参数r,之后,指针R将被清除,指针R将获得内存块m2的所有权。在下一行,指针R的箭头运算符调用中的操作ACCESS(R)将触发取消引用空bug,因为它打破了ACCESS操作的前提条件。
第8行:操作INSPECT(r)将分叉路径,并在true或false分支上将m的状态分别更改为Usable或Null。然后,当调用指针r的运算符*时,使用操作ACCESS(r)在假分支上报告取消引用空值问题。

4. 效能评估

4.1 Rearch Questions

RQ 1:有效性。我们的工具可以检测到多少手工制作和真实世界的MisSP?
RQ 2:可用性。将消耗多少时间和内存?错误警报的原因是什么?
RQ 3:Discoveries。我们可以从统计数据中了解哪些关于MisSP的信息?

4.2 实验环境

基于Clang Static Analyzer(CSA)9.0.0实现了工具Spelton。
环境:Linux + 双Intel至强cpu(56线程) + 256GB内存

4.3 benchmark选择

(1)handmade
912个handmade代码片段,468个Juliet Test Suite v1.3(JTS)缺陷代码数据集所生成的代码片段,其余426个片段是从JTS中的四种类型的内存错误半自动变异而来的。
inserted bugs (Pos.) and corresponding fixes (Neg.),变异的代码按其原始CWE ID分类。
在这里插入图片描述

(2)GitHub的9个C++开源项目
the numbers of smart pointers of class members (#F), local variables (#L) and reference variables (#R), as well as method calls with ACCESS operations (#A) among all calls (#All).
Kloc: 千行代码
在这里插入图片描述

4.4 Effectiveness on Handmade Benchmark

Spelton可以找到几乎所有的bug,并且没有错误警报。只有两个错误否定是由处理不当的switch case语句引起的。而其他工具只能检测出一部分错误。

在这里插入图片描述

4.5 Effectiveness on Open-Source Projects

Spelton遗漏的错误是那些由原始指针与智能指针协作触发的内存错误。最常报告的bug是空指针解引用。
在这里插入图片描述

4.6 Evaluation on Usability

超过一半(115/208)的误报(false positive)是由未分析的代码触发的。
分为三类:
1.未做声明的函数(如来自第三方库)(22个)
2.隐式约束,这些约束存在于整个程序中,但无法在当前分析上下文中收集。(88个)
3.失效的断言(assertion),当在断言失效的情况下,编译分析代码,代码中的断言宏将替换为无效表达式。由于在解析过程中删除了断言中的条件,Spelton无法在断言中添加相应的约束,因此会导致误报。(5个)

4.7 Discoveries

1.所有的bad assignment and type mismatch bugs 都是由于没有使用函数std::make_unique和std:∶make_shared来创建新的智能指针造成的。
正确做法:

在这里插入图片描述
2.开发人员应该更多地关注共享指针。尽管unique shared bug不会导致崩溃或资源耗尽,但这些bug将严重影响程序的效率。此外,共享指针也可能触发循环引用错误。
3.智能指针不能免疫所有类型的内存错误,尤其是空指针取消引用错误。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值