[发明专利]一种面向堆操作程序的内存泄漏检测方法有效
申请号: | 201210041025.7 | 申请日: | 2012-02-22 |
公开(公告)号: | CN102662825A | 公开(公告)日: | 2012-09-12 |
发明(设计)人: | 王戟;董龙明;陈立前;董威;刘万伟;李仁见 | 申请(专利权)人: | 中国人民解放军国防科学技术大学 |
主分类号: | G06F11/36 | 分类号: | G06F11/36 |
代理公司: | 国防科技大学专利服务中心 43202 | 代理人: | 郭敏 |
地址: | 410073 湖*** | 国省代码: | 湖南;43 |
权利要求书: | 查看更多 | 说明书: | 查看更多 |
摘要: | |||
搜索关键词: | 一种 面向 操作 程序 内存 泄漏 检测 方法 | ||
1.一种面向堆操作程序的内存泄漏检测方法,其特征在于包括以下步骤:
第1步,利用编译器平台对被检测程序进行词法分析、语法分析,生成被检测程序的抽象语法树、控制流图、过程调用图;
第2步,预处理:
2.1切片,即将那些没有使用任何指针类型变量的赋值语句从程序中删除,得到切片后的程序;
2.2将经过切片后的程序中不符合标准形式的指针赋值语句按照转换规则转换成标准形式;
第3步,根据函数中每个指针变量的别名信息定义指针的扩展类型,得到程序的堆内存抽象状态;堆操作程序中,指针变量p的扩展类型定义 为:<f1:<dist;2PVar>;f2:<dist,2PVar>;...fi:<dist;2PVar>...;fn:<dist;2PVar>>,其中:f1,f2,...fi,...,fn分别表示p指向内存单元中指针域的名字,1≤i≤n,即:p指向由n个指针域聚集的内存单元,内存单元又称为内存结点;变量dist表示堆中内存结点距离指针p的值;2PVar表示所有指向距离p所指向内存结点值为dist的内存结点构成的指针变量集,称为指针别名集;变量dist值的范围为:0、1和2,其中:元素0和1表示堆内存中距离p所指向的内存结点精确值,值2是一个抽象值,表示通过某个指针域fi两次或两次以上的路由次数,在堆内存中这样得到的内存结点又称摘要结点;指针集2PVar中有两个特殊的元素:空集 表示堆内存中没有任何指针变量指向该内存单元,而该内存单元在堆内存中已经被分配;⊥表示某个指针变量p或指针域fi的值为null,表示该指针变量值为无效内存地址,p或指针域fi所指向的内存单元在堆中还没有被分配;堆操作程序HP的活性指针变量是程序片段中一类被使用或修改的指针变量,由谓词LivePVar表示;堆内存局部抽象状态 是具有活性指针变量的扩展类型构成的集合,即: pi表示任意一个具有活性的指针变量, 表示pi的扩展类型;
第4步,从被检测程序的过程调用图中自顶向下选择某个函数f,并将函数f入口处的抽象状态 设置为空,根据前向数据流迭代方法进行过程内内存泄漏检测,得到堆操作程序中基本语句关于堆内存抽象状态的迁移关系,前向数据流迭代方法是:
4.1初始化函数f中每个程序点i的堆内存抽象状态 置为空,并将队列W置 为空,W是一个先进先出FIFO的队列,基本元素为 对,s为语句, 为堆内存局部抽象状态;
4.2将函数f的入口语句s0和抽象状态 加入到队列W;
4.3判断队列W是否为空,如果为空则转第6步,如果不为空则执行4.4;
4.4从队列W中弹出项 根据语句s的类型转换抽象状态 得到新的抽象状态 具体方法如下:
4.4.1如果语句s为基本指针赋值语句,则按7种指针赋值语句的类型转换状态 得到新的抽象状态 并从控制流图中语句s的后继语句集Succ(s)中选择某个元素s’,然后执行4.5;按7种指针赋值语句的类型转换 的方法是:
(1)指针赋值语句p=null,转换规则是:在状态 中,首先从通过某个指针域fi路由可达p指向内存结点的指针别名集中删除p,然后将 置为null,即:将 中所有通过fi路由距离值为0、1和2的指针别名集置为⊥,得到新的抽象状态 如果状态 中指针p所指向的内存结点存在且没有被其他指针变量或堆内存中其他内存结点通过某个指针域路由可达,则发生内存泄漏,将该语句s和抽象状态 加入到内存泄漏队列heapleakListF中,heapleakListF是保存所有发生内存泄漏的语句和状态的队列,基本元素为:语句和抽象状态对
(2)语句p->fm=null,转换规则是:在状态 中,指针变量x代表能够通过某个指针域fi路由可达p指向内存结点的指针变量;首先,修改x的扩展类型:如果x与p别名,即:x到p的距离为0,则从 中将通过fi路由距离值为1和2的指针别名集置为空;如果x到p的距离值为1或2,则从 中通过fi路由距离为2的指针别名集中删除 中通过fi路由距离值为1和2的指针别名集;然后,将 中通过fm路由距离值为1和2的指针别名集置为空,得到新的抽象状态 如果状态 中p指向内存结点中的fm指向的内存结点存在且没有被其他指针变量或其他内存结点通过fi路由可达,则发生内存泄漏,将语句s和状态 加入到内存泄漏队列heapleakListF中;
(3)指针拷贝语句p=q,转换规则是:首先,在状态 下按照规则(1)执行语句p=null得到中间抽象状态 然后在中间抽象状态 下,将 赋值给 即将p 的指向修改为q指向的结点,得到新的抽象状态 如果状态 中p指向的内存结点存在且没有被其他指针变量或堆内存中其他内存结点通过某个指针域路由可达,则发生内存泄漏,将语句s和状态 加入到内存泄漏队列heapleakListF中;
(4)语句p=q->fm,转换规则是:首先,在状态 下按照规则(1)执行语句p=null得到中间抽象状态 然后在中间抽象状态 下,将 中通过fm路由距离值为1的指针别名集赋值给与 中通过某个指针域fi路由距离值为0的指针别名集,将p加入到 中通过fi路由距离值为1的指针别名集中,得到新的抽象状态 如果状态 中p指向的内存结点存在且没有被其他指针变量或堆内存中其他内存结点通过某个指针域路由可达,则发生内存泄漏,将语句s和状态 加入到内存泄漏队列heapleakListF中;
(5)语句p->fm=q,转换规则是:首先,在状态 下按照规则(1)执行语句p->fm=null得到中间抽象状态 然后在中间抽象状态 下,集合Q表示 中通过某个指针域fi路由距离为0的指针别名集,指针变量x表示抽象状态 中能够通过fi一次或多次路由到达p指向的内存结点的指针;按照以下规则修改中间抽象状态 首先,修改集合Q中指针变量y的扩展类型 将 中通过fi路由距离为0的指针别名集加入到 中通过fi路由距离为1的指针别名集中,将 中通过fi路由距离为1和2的指针别名集添加到 中通过fi路由距离为2的指针别名集中;然后,将通过fi路由距离q值为0、1和2的指针别名集同q一起添加到 中通过fi路由距离为2的指针别名集中,得到新的抽象状态 如果状态 中p指向的内存结点中fm指向的内存结点存在且没有被其他指针变量或堆内存中其他内存结点通过某个指针域路由可达,则发生内存泄漏,将语句s和状态 加入到内存泄漏队列heapleakListF中;
(6)内存分配语句p=malloc(),转换规则是:首先,在状态 下按照规则(1)执行语句p=null得到中间抽象状态 然后在中间抽象状态 下,新申请一个内存结点并且将该内存结点的地址赋值给指针p,即:将 中通过某个指针域fi路由距离 为0的指针别名集置为空集 通过fi路由距离为1和2的指针别名集置为⊥,得到新的抽象状态 如果状态 中p指向的内存结点存在且没有被其他指针变量或堆内存中其他内存结点通过某个指针域fi路由可达,则发生内存泄漏,将语句s和状态 加入到内存泄漏队列heapleakListF中;
(7)内存释放语句free(p),转换规则是:在状态 中,指针变量w表示活指针变量集LivePVar(HP)中除p所有其他指针变量,首先,从 中通过某个指针域fi路由距离值为0、1和2的指针别名集中删除 中通过fi路由距离为0的指针别名集,然后将 中通过fi路由距离值为0、1和2的指针别名集置为⊥,得到新的抽象状态 如果状态 中p指向内存结点中某个指针域所指向的内存结点存在没有被其他指针变量或堆内存中其他内存结点通过某个指针域路由所可达,则发生内存泄漏,将语句s和状态 加入到内存泄漏队列heapleakListF中;
4.4.2如果语句s为switch条件选择语句,则:首先在当前堆内存抽象状态 下求解switch语句条件的真值,然后根据条件真值从Succ(s)中选择下一条执行语句s’,并将s’作为语句s的后继语句,状态 作为新的抽象状态 执行4.5;
4.4.3如果语句s为无条件跳转语句,则:将目标语句s’作为语句s的后继语句,状态 作为新的抽象状态 执行4.5;
4.4.4如果语句s为函数调用语句,则执行第5步,得到新的抽象状态 从Succ(s)中选择某个元素s’,作为s的后继语句;
4.4.5如果语句s是函数返回语句return e,则在抽象状态 下,将指针变量e的扩展类型作为函数返回值的扩展类型,全局指针变量的扩展类型不变,其他局部指针变量的扩展类型赋值置空,得到新的抽象状态 并作为函数f的出口状态 出口语句s’作为返回语句s的后继语句,然后执行4.5;
4.5将新的抽象状态 与后继语句s’的初始状态 通过合并操作Join得到该程序点新的抽象状态 执行4.6步;合并操作是:当且仅当任意两个抽象状态 和 存在包括关系时才能合并,否则两个抽象状态分别作为合并操作的元素;两个堆内存抽象状态 和 存在包含关系 当且仅当:状态 中任意元素在状态 中; 合并操作由公式表示为:
4.6将合并后的堆抽象状态 采用饱和操作达到饱和状态 饱和操作具体步骤如下:
4.6.1将标记变量modified初始化为假;
4.6.2反自反操作:遍历抽象状态 中每个指针变量x1,从 中通过某个指针域fi路由距离为0的指针别名集中删除指针x1,如果某个指针别名集被修改了,将modified置为真;
4.6.3对称操作:遍历抽象状态 中每个指针变量x2,从 中通过某个指针域fi路由距离为0的指针别名集中任意取出某个指针变量y2,如果 中所有通过fi路由距离为0的指针别名集不包含x2,则将x2加入 中到通过fi路由距离为0的指针别名集,如果某个指针别名集被修改了,将modified置为真;
4.6.4传递操作:遍历抽象状态 中每个指针变量x3,从 中通过某个指针域fi路由距离为某个值d1的指针别名集中任意取出某个指针变量y,在 中通过某个指针域路由距离为某个值d2得到指针别名集Q2,如果指针别名集Q2中某个指针变量z不在 中通过fi路由距离为d1+d2的指针别名集中,则将z加入到 中通过fi路由距离为d1+d2的指针别名集中,如果某个指针别名集被修改了,将modified置为真;
4.6.5判断modified的值,如果为假,状态 达到饱和状态 转4.7步;否则转4.6.1步;
4.7如果饱和状态 与原始状态 不同,则将饱和状态 作为新的原始状态 并且将饱和状态 和后继语句s’加入到W中,转4.3;
第5步,对堆操作程序进行过程间的内存泄漏检测,方法是:
5.1获取过程调用语句e=f(e1,e2,...,ek)的初始化信息,被调用过程名为:f,形式参数为:p1,p2,...,pk,实际参数为:e1,e2,...,ek,其中:ph代表形式参数,eh为ph相对 应的实际参数,1≤h≤k,返回值为:retf,局部指针变量集为:LVarf,全局指针变量集为:GVarf,执行函数调用语句前的堆内存抽象状态为
5.2在堆内存抽象状态 下执行调用语句的状态迁移,得到被调用函数的堆内存初始状态 过程如下:
5.2.1将状态 中全局指针变量集GVarf中任意全局指针变量g的扩展类型传递给被调用过程,即:状态 中g的 等于状态 中g的
5.2.2将状态 中实际参数eh的 传递给形式参数ph,作为被调用入口处ph的 即:状态 中 的值为状态 中 的值;
5.2.3状态 中局部指针变量集LVarf中的任意局部指针变量l的扩展类型 初始化为空;
5.3将函数f和初始状态 作为参数,采用第4步前向数据流迭代方法对函数f进行过程内内存泄漏检测,得到函数出口处堆内存新的抽象状态
5.4将堆内存状态 传递给调用过程,得到新的抽象状态 按照如下步骤:
5.4.1将状态 中指针类型返回值retf的扩展类型传递给调用过程,作为状态 下指针e的扩展类型;
5.4.2状态 中全局指针变量g的扩展类型 传递给调用过程时不变,作为状态 下g的
5.4.3其他局部指针变量的扩展类型在过程调用前后不变,即:状态 中其他局部指针变量的扩展类型的值为状态 中的相应局部指针变量扩展类型的值;
第6步,统计堆操作程序内存泄漏检测结果数据:
6.1根据控制流图上各个程序点中关于堆内存抽象状态的信息,输出各个程序点的入口语句的堆内存抽象状态和出口处的堆内存抽象状态;
6.2根据内存泄漏队列heapleakListF的内容,输出所有可能发生内存泄漏的程序语句s和状态 并统计内存泄漏的数目;
6.3筛选可能的内存泄漏错误,统计出检测的误报数,并得到误报率;
6.4根据编译平台和系统运行时信息,得到内存泄漏检测方法消耗系统资源的情况。
该专利技术资料仅供研究查看技术是否侵权等信息,商用须获得专利权人授权。该专利全部权利属于中国人民解放军国防科学技术大学,未经中国人民解放军国防科学技术大学许可,擅自商用是侵权行为。如果您想购买此专利、获得商业授权和技术合作,请联系【客服】
本文链接:http://www.vipzhuanli.com/pat/books/201210041025.7/1.html,转载请声明来源钻瓜专利网。
- 上一篇:利用空间混合索引机制检测钓鱼网页的方法
- 下一篇:一种开口手套