一种内存泄漏调试方法及装置.pdf

上传人:e1 文档编号:1285635 上传时间:2018-04-12 格式:PDF 页数:16 大小:1.21MB
返回 下载 相关 举报
摘要
申请专利号:

CN201610835054.9

申请日:

2016.09.20

公开号:

CN106502880A

公开日:

2017.03.15

当前法律状态:

实审

有效性:

审中

法律详情:

实质审查的生效IPC(主分类):G06F 11/36申请日:20160920|||公开

IPC分类号:

G06F11/36

主分类号:

G06F11/36

申请人:

东软集团股份有限公司

发明人:

杨枭

地址:

110179 辽宁省沈阳市浑南新区新秀街2号

优先权:

专利代理机构:

北京鼎佳达知识产权代理事务所(普通合伙) 11348

代理人:

刘喆;刘铁生

PDF下载: PDF下载
内容摘要

本发明公开了一种内存泄漏调试方法及装置,涉及计算机技术领域,主要目的在于解决在统一内存申请的情况下无法对造成内存泄漏的代码模块进行定位的问题。本发明的方法包括:在内存申请函数被调用时,调用内存泄露检测函数,其中程序中的不同模块通过调用所述内存申请函数申请内存;通过执行所述内存泄露检测函数获取未释放内存的内存申请调试信息,所述内存申请调试信息包括申请内存的模块编号及其对应的申请内存的栈信息;将栈信息相同的模块确定为处于同一个统一内存申请框架下的模块;在同一个统一内存申请框架下,将未释放内存的数量最多的模块编号所对应的模块确定为存在内存泄露的可疑模块。

权利要求书

1.一种内存泄漏调试方法,其特征在于,所述方法包括:
在内存申请函数被调用时,调用内存泄露检测函数,其中程序中的不同模块通过调用
所述内存申请函数申请内存;
通过执行所述内存泄露检测函数获取未释放内存的内存申请调试信息,所述内存申请
调试信息包括申请内存的模块编号及其对应的申请内存的栈信息;
将栈信息相同的模块确定为处于同一个统一内存申请框架下的模块;
在同一个统一内存申请框架下,将未释放内存的数量最多的模块编号所对应的模块确
定为存在内存泄露的可疑模块。
2.根据权利要求1所述的方法,其特征在于,在将栈信息相同的模块确定为处于同一个
统一内存申请框架下的模块之后,所述方法还包括:
在多个统一内存申请框架下,统计每个统一内存申请框架下的未释放内存的内存申请
调试信息,将未释放内存的内存申请调试信息最多的统一内存申请框架确定为存在内存泄
露的可疑统一内存申请框架;
在存在内存泄露的可疑统一内存申请框架下,将未释放内存的数量最多的模块编号所
对应的模块确定为存在内存泄露的可疑模块。
3.根据权利要求1或2所述的方法,其特征在于,在将未释放内存的数量最多的模块编
号所对应的模块确定为存在内存泄露的可疑模块之后,所述方法还包括:
根据可疑模块对应的模块编号,在内存申请函数位置挂载第一条件断点,使得程序运
行至内存申请函数位置时暂停运行;其中,所述第一条件断点用于在程序中的可疑模块调
用内存申请函数申请内存时暂停程序;
在程序暂停运行时获取申请内存的首地址,在申请内存的首地址挂载第二条件断点以
便监听所述申请内存的首地址的写操作;
继续运行程序,当所述申请内存的首地址存在写操作时停止运行程序;
将程序运行停止时的代码位置确定为所述可疑模块存在内存泄露的可疑代码位置。
4.根据权利要求3所述的方法,其特征在于,在将程序运行停止时的代码位置确定为所
述可疑模块存在内存泄露的可疑代码位置之后,所述方法还包括:
根据所述可疑模块的函数功能和/或流程,确定所述可疑模块是否为使用内存后无法
释放内存的模块。
5.根据权利要求4所述的方法,其特征在于,所述方法还包括:
对内存泄露检测函数获取的未释放内存的内存申请调试信息中的所有模块编号所对
应的模块进行检测,确定是否存在使用内存后无法释放内存的模块。
6.根据权利要求1所述的方法,其特征在于,
所述内存申请调试信息还包括申请内存的首地址;
所述通过执行所述内存泄露检测函数获取未释放内存的内存申请调试信息包括:
通过执行所述内存泄露检测函数记录已申请内存的内存申请调试信息,并将其保存在
全局结构中;
当所述内存泄露检测函数检测到内存释放时,将已申请内存的首地址与释放内存的首
地址相同的内存申请调试信息从全局结构中删除。
7.根据权利要求6所述的方法,其特征在于,通过执行所述内存泄露检测函数获取未释
放内存的内存申请调试信息包括:根据特定条件下进行内存释放的函数特点对内存泄露检
测函数预先进行配置,禁止将特定条件下进行内存释放的内存申请调试信息保存在全局结
构中。
8.根据权利要求1所述的方法,其特征在于,在内存申请函数被调用时,调用内存泄露
检测函数包括:
预先注册内存申请函数的钩子函数,以便在内存申请函数被调用时通过所述钩子函数
调用内存泄露检测函数。
9.一种内存泄漏调试装置,其特征在于,所述装置包括:
调用单元,用于在内存申请函数被调用时,调用内存泄露检测函数,其中程序中的不同
模块通过调用所述内存申请函数申请内存;
获取单元,用于通过执行所述内存泄露检测函数获取未释放内存的内存申请调试信
息,所述内存申请调试信息包括申请内存的模块编号及其对应的申请内存的栈信息;
第一确定单元,用于将栈信息相同的模块确定为处于同一个统一内存申请框架下的模
块;
第二确定单元,用于在同一个统一内存申请框架下,将未释放内存的数量最多的模块
编号所对应的模块确定为存在内存泄露的可疑模块。
10.根据权利要求9所述的装置,其特征在于,所述装置还包括:
第三确定单元,用于在第一确定单元将栈信息相同的模块确定为处于同一个统一内存
申请框架下的模块之后,在多个统一内存申请框架下,统计每个统一内存申请框架下的未
释放内存的内存申请调试信息,将未释放内存的内存申请调试信息最多的统一内存申请框
架确定为存在内存泄露的可疑统一内存申请框架;
所述第二确定单元,用于在第三确定单元确定的存在内存泄露的可疑统一内存申请框
架下,将未释放内存的数量最多的模块编号所对应的模块确定为存在内存泄露的可疑模
块。

说明书

一种内存泄漏调试方法及装置

技术领域

本发明涉及计算机技术领域,特别是涉及一种内存泄漏调试方法及装置。

背景技术

内存是计算机系统一种重要的公共资源,程序运行时都需要将数据存放在内存
中,其作用是用于暂时存放中央处理器(Central Processing Unit,CPU)中的运算数据,以
及与硬盘等外部存储器交换的数据。正常情况下,程序运行时申请内存,结束后再释放掉申
请的内存,从而保证系统对内存使用的持续性。然而在实际情况下,由于程序的设计错误或
者编码失误会造成内存申请后没有释放,这些没有释放的内存脱离了操作系统的内存管理
机制,导致申请的内存无法再次使用,这种情况称为内存泄漏。泄漏的内存本质上没有消
失,只是处于一种不受管制的状态。

针对内存泄露问题,目前有很多内存泄露调试工具,例如Valgrind工具及Memleak
工具,这些工具都可以在代码中直接定位到内存泄露时内存申请的具体位置。但是在申请
内存时,还存在一种统一内存申请的情况,例如linux内核中skb结构,当网卡驱动程序收到
数据包后统一申请内存,但是根据数据包的类型(TCP,UDP,ICMP等),需要将不同类型数据
包分给对应的代码模块进行处理,不同的代码模块在程序源代码的同一位置调用同一个内
存申请函数申请各自使用的内存。在这种统一内存申请的情况下,只有一个内存申请的位
置,并且内存释放由各个模块负责,此时当出现内存泄露时,内存泄露调试工具定位的都是
统一内存申请的位置,而不能区分到底是哪个模块没有释放内存。因此,如何在统一内存申
请的情况下对造成内存泄漏的代码模块进行快速定位成为亟待解决的技术问题。

发明内容

有鉴于此,本发明提出了一种内存泄漏调试方法及装置,主要目的在于解决在统
一内存申请的情况下无法对造成内存泄漏的代码模块进行定位的问题。

依据本发明的第一个方面,本发明提供了一种内存泄漏调试方法,包括:

在内存申请函数被调用时,调用内存泄露检测函数,其中程序中的不同模块通过
调用所述内存申请函数申请内存;

通过执行所述内存泄露检测函数获取未释放内存的内存申请调试信息,所述内存
申请调试信息包括申请内存的模块编号及其对应的申请内存的栈信息;

将栈信息相同的模块确定为处于同一个统一内存申请框架下的模块;

在同一个统一内存申请框架下,将未释放内存的数量最多的模块编号所对应的模
块确定为存在内存泄露的可疑模块。

进一步地,在将栈信息相同的模块确定为处于同一个统一内存申请框架下的模块
之后,所述方法还包括:

在多个统一内存申请框架下,统计每个统一内存申请框架下的未释放内存的内存
申请调试信息,将未释放内存的内存申请调试信息最多的统一内存申请框架确定为存在内
存泄露的可疑统一内存申请框架;

在存在内存泄露的可疑统一内存申请框架下,将未释放内存的数量最多的模块编
号所对应的模块确定为存在内存泄露的可疑模块。

进一步地,在将未释放内存的数量最多的模块编号所对应的模块确定为存在内存
泄露的可疑模块之后,所述方法还包括:

根据可疑模块对应的模块编号,在内存申请函数位置挂载第一条件断点,使得程
序运行至内存申请函数位置时暂停运行;其中,所述第一条件断点用于在程序中的可疑模
块调用内存申请函数申请内存时暂停程序;

在程序暂停运行时获取申请内存的首地址,在申请内存的首地址挂载第二条件断
点以便监听所述申请内存的首地址的写操作;

继续运行程序,当所述申请内存的首地址存在写操作时停止运行程序;

将程序运行停止时的代码位置确定为所述可疑模块存在内存泄露的可疑代码位
置。

进一步地,在将程序运行停止时的代码位置确定为所述可疑模块存在内存泄露的
可疑代码位置之后,所述方法还包括:

根据所述可疑模块的函数功能和/或流程,确定所述可疑模块是否为使用内存后
无法释放内存的模块。

进一步地,所述方法还包括:

对内存泄露检测函数获取的未释放内存的内存申请调试信息中的所有模块编号
所对应的模块进行检测,确定是否存在使用内存后无法释放内存的模块。

具体地,所述内存申请调试信息还包括申请内存的首地址;

所述通过执行所述内存泄露检测函数获取未释放内存的内存申请调试信息包括:

通过执行所述内存泄露检测函数记录已申请内存的内存申请调试信息,并将其保
存在全局结构中;

当所述内存泄露检测函数检测到内存释放时,将已申请内存的首地址与释放内存
的首地址相同的内存申请调试信息从全局结构中删除。

具体地,通过执行所述内存泄露检测函数获取未释放内存的内存申请调试信息包
括:根据特定条件下进行内存释放的函数特点对内存泄露检测函数预先进行配置,禁止将
特定条件下进行内存释放的内存申请调试信息保存在全局结构中。

具体地,在内存申请函数被调用时,调用内存泄露检测函数包括:

预先注册内存申请函数的钩子函数,以便在内存申请函数被调用时通过所述钩子
函数调用内存泄露检测函数。

依据本发明的第二个方面,本发明提供了一种内存泄漏调试装置,包括:

调用单元,用于在内存申请函数被调用时,调用内存泄露检测函数,其中程序中的
不同模块通过调用所述内存申请函数申请内存;

获取单元,用于通过执行所述内存泄露检测函数获取未释放内存的内存申请调试
信息,所述内存申请调试信息包括申请内存的模块编号及其对应的申请内存的栈信息;

第一确定单元,用于将栈信息相同的模块确定为处于同一个统一内存申请框架下
的模块;

第二确定单元,用于在同一个统一内存申请框架下,将未释放内存的数量最多的
模块编号所对应的模块确定为存在内存泄露的可疑模块。

进一步地,所述装置还包括:

第三确定单元,用于在第一确定单元将栈信息相同的模块确定为处于同一个统一
内存申请框架下的模块之后,在多个统一内存申请框架下,统计每个统一内存申请框架下
的未释放内存的内存申请调试信息,将未释放内存的内存申请调试信息最多的统一内存申
请框架确定为存在内存泄露的可疑统一内存申请框架;

所述第二确定单元用于在第三确定单元确定的存在内存泄露的可疑统一内存申
请框架下,将未释放内存的数量最多的模块编号所对应的模块确定为存在内存泄露的可疑
模块。

进一步地,所述装置还包括:

第一处理单元,用于在将未释放内存的数量最多的模块编号所对应的模块确定为
存在内存泄露的可疑模块之后,根据可疑模块对应的模块编号,在内存申请函数位置挂载
第一条件断点,使得程序运行至内存申请函数位置时暂停运行;其中,所述第一条件断点用
于在程序中的可疑模块调用内存申请函数申请内存时暂停程序;

第二处理单元,用于在程序暂停运行时获取申请内存的首地址,在申请内存的首
地址挂载第二条件断点以便监听所述申请内存的首地址的写操作;

在申请内存的首地址挂载第二条件断点后继续运行程序;

停止单元,用于当所述申请内存的首地址存在写操作时停止运行程序;

第四确定单元,用于将程序运行停止时的代码位置确定为所述可疑模块存在内存
泄露的可疑代码位置。

进一步地,所述装置还包括:

第五确定单元,用于在将程序运行停止时的代码位置确定为所述可疑模块存在内
存泄露的可疑代码位置之后,根据所述可疑模块的函数功能和/或流程,确定所述可疑模块
是否为使用内存后无法释放内存的模块。

进一步地,所述装置还包括:

轮询单元,用于对内存泄露检测函数获取的未释放内存的内存申请调试信息中的
所有模块编号所对应的模块进行检测,确定是否存在使用内存后无法释放内存的模块。

具体地,所述内存申请调试信息还包括申请内存的首地址;

所述获取单元包括:

保存模块,用于通过执行所述内存泄露检测函数记录已申请内存的内存申请调试
信息,并将其保存在全局结构中;

删除模块,用于当所述内存泄露检测函数检测到内存释放时,将已申请内存的首
地址与释放内存的首地址相同的内存申请调试信息从全局结构中删除。

具体地,所述获取单元还包括:

配置模块,用于根据特定条件下进行内存释放的函数特点对内存泄露检测函数预
先进行配置,禁止将特定条件下进行内存释放的内存申请调试信息保存在全局结构中。

具体地,所述调用单元包括:

注册模块,用于预先注册内存申请函数的钩子函数;

调用模块,用于在内存申请函数被调用时通过所述钩子函数调用内存泄露检测函
数。

借由上述技术方案,本发明实施例提供的一种内存泄漏调试方法及装置,通过为
程序中的不同模块进行编号,并利用内存泄露检测函数记录模块申请内存时的栈信息来确
定统一内存申请框架,最后根据统一内存申请框架下未释放内存的数量最多的模块编号所
对应的模块确定最为可能存在内存泄露的模块。本发明避免了现有的内存泄露调试工具在
统一内存申请的情况下,定位的都是统一内存申请的位置,而不能区分到底是哪个模块没
有释放内存的缺陷。

上述说明仅是本发明技术方案的概述,为了能够更清楚了解本发明的技术手段,
而可依照说明书的内容予以实施,并且为了让本发明的上述和其它目的、特征和优点能够
更明显易懂,以下特举本发明的具体实施方式。

附图说明

通过阅读下文优选实施方式的详细描述,各种其他的优点和益处对于本领域普通
技术人员将变得清楚明了。附图仅用于示出优选实施方式的目的,而并不认为是对本发明
的限制。而且在整个附图中,用相同的参考符号表示相同的部件。在附图中:

图1示出了本发明实施例提供的一种内存泄漏调试方法的流程示意图;

图2示出了本发明实施例提供的一种内存泄漏调试装置的组成框图;

图3示出了本发明实施例提供的一种内存泄漏调试装置的组成框图。

具体实施方式

下面将参照附图更加详细地描述本公开的示例性实施例。虽然附图中显示了本公
开的示例性实施例,然而应当理解,可以以各种形式实现本公开而不应被这里阐述的实施
例所限制。相反,提供这些实施例是为了能够更透彻地理解本公开,并且能够将本公开的范
围完整的传达给本领域的技术人员。

目前有很多内存泄露调试工具,这些工具都可以在代码中直接定位到内存泄露时
内存申请的具体位置。但是在统一内存申请的情况,只有一个内存申请的位置,并且内存释
放由程序中的各个模块负责,此时当出现内存泄露时,内存泄露调试工具定位的都是统一
内存申请的位置,而不能区分到底是哪个模块没有释放内存。

为了解决上述问题,本发明实施例提供了一种内存泄漏调试方法,主要是通过程
序中的不同模块在申请内存时的栈信息,确定统一内存申请框架下的模块,再按照同一个
统一内存申请框架下未释放内存的模块编号的数量,确定未释放内存的数量最多的模块编
号所对应的模块最为可能存在内存泄露。如图1所示,该方法包括:

101、在内存申请函数被调用时,调用内存泄露检测函数,其中程序中的不同模块
通过调用所述内存申请函数申请内存。

源程序是指未经编译的,按照一定的程序设计语言规范书写的,人类可读的文本
文件,而在计算机中运行的程序是对源程序进行编译后得到的。现有在设计程序时常常会
通过函数来实现模块化程序设计,因此程序运行过程中在申请内存时,是由不同的模块来
申请并使用各自的内存,同样的,释放内存也由不同的模块各自负责。

基于上述原因,本发明实施例在对程序运行过程中发生的内存泄露进行检测时,
可以基于程序中的不同模块,来对内存泄露的位置进行定位。首先需要在程序的众多模块
中定位可能存在内存泄露的模块。由于某个模块在申请内存时,都会产生该模块需要的内
存信息,包括申请内存的大小以及申请完成时此次内存申请的首地址,但是为了定位存在
内存泄露的模块,仅仅依靠上述内存信息是不够的,还需要额外获取申请内存时产生的其
他信息,本发明实施例将申请内存时额外获取的信息称为内存申请调试信息。所述内存申
请调试信息除了具有申请内存的大小及首地址外,还包括:申请内存的模块编号、栈信息
等。因此,若要找到存在内存泄露的模块,就需要获取内存申请调试信息,而在获取内存申
请调试信息时,通过人工方式明显无法完成,需要依靠特定的功能函数来自动记录。因此,
本发明实施例需要执行步骤101在内存申请函数被调用时,调用内存泄露检测函数。也就是
说,在程序运行过程中当程序中的内存申请函数被调用时,需要立即调用内存泄露检测函
数,用于记录内存申请调试信息。

102、通过执行所述内存泄露检测函数获取未释放内存的内存申请调试信息,所述
内存申请调试信息包括申请内存的模块编号及其对应的申请内存的栈信息。

当通过步骤101调用了内存泄露检测函数之后,程序继续运行,程序中不同模块的
申请内存的信息以及释放内存的信息都会被内存泄露检测函数获取,内存泄露检测函数对
内存申请调试信息进行保存,在内存释放时将释放内存对应的内存申请调试信息进行删
除。这些内存申请调试信息包括:模块编号、申请内存的首地址、申请内存的大小以及栈信
息;其中,为了在程序运行过程中对程序中的各个模块进行有效区分,本发明实施例对不同
的模块分配了不同的编号;而栈信息则记录了各个模块编号对应的模块在调用内存申请函
数时的函数地址、函数参数、函数间的调用逻辑关系等。因此当停止对程序进行内存泄露检
测时,所述内存泄露检测函数会获取到未释放内存的内存申请调试信息。

103、将栈信息相同的模块确定为处于同一个统一内存申请框架下的模块。

当程序中的不同模块申请内存时,不同的模块可能会调用程序中同一个位置的内
存申请函数,也可能会调用不同位置的内存申请函数,当不同模块调用同一个位置的内存
申请函数时,这些模块处于同一个统一内存申请框架下。由于在步骤102中通过内存泄露检
测函数记录了未释放内存的内存申请调试信息,并且内存申请调试信息中具有模块编号及
其对应的栈信息,而栈信息中记录有内存申请时调用的内存申请函数的地址;若某些模块
编号对应的栈信息相同,则说明这些模块编号对应的模块调用同一个内存申请函数。因此
根据栈信息的相同与否,可以确定哪些模块编号对应的模块处于同一个统一内存申请框架
下,也就是将栈信息相同的模块确定为处于同一个统一内存申请框架下的模块。其中,内存
申请函数的位置也就是内存申请函数在程序源代码中所在具体行号的位置。这里需要说明
的是,在步骤103中根据栈信息确定的统一内存申请框架可以具有多个,每个统一内存申请
框架下各个模块申请的内存只能被该框架下的各个模块使用。

104、在同一个统一内存申请框架下,将未释放内存的数量最多的模块编号所对应
的模块确定为存在内存泄露的可疑模块。

当确定了同一个统一内存申请框架后,每个统一内存申请框架下都可能具有许多
模块编号。其中,由于一个模块可能多次调用同一个位置的内存申请函数,因此,在一个统
一内存申请框架下记录的同一个模块编号也会具有多个。由于内存泄露检测函数记录的内
存申请调试信息中的模块编号都是未释放内存的模块对应的模块编号,同一个模块编号出
现的次数越多,说明该模块编号对应的模块越有可能存在内存泄露。因此在同一个统一内
存申请框架下,未释放内存的数量最多的模块编号所对应的模块可以被确定为存在内存泄
露的可疑模块。若通过步骤103确定了多个统一内存申请框架,则在每个统一内存申请框架
下,都可以确定一个存在内存泄露的可疑模块。例如,在一个统一内存申请框架下,记录的
模块编号A有3个,模块编号B有1个,模块编号C有5个,模块编号D有7个,由于模块编号D的数
量最多,因此可以将模块编号D确定为该统一内存申请框架下存在内存泄露的可疑模块。若
在另一个统一内存申请框架下,记录的模块编号A有2个,模块编号B有3个,模块编号C有5
个,则可以将模块编号C确定为该统一内存申请框架下存在内存泄露的可疑模块。

本发明实施例提供的一种内存泄漏调试方法,通过为程序中的不同模块进行编
号,并利用内存泄露检测函数记录模块申请内存时的栈信息来确定统一内存申请框架,最
后根据统一内存申请框架下数量最多的模块编号所对应的模块确定最为可能存在内存泄
露的模块。本发明避免了现有的内存泄露调试工具在统一内存申请的情况下,定位的都是
统一内存申请的位置,而不能区分到底是哪个模块没有释放内存的缺陷。

为了更好的对本发明实施例提供的内存泄露调试方法进行说明,以下实施例将针
对上述各步骤进行细化和扩展。

由于本发明实施例在检测程序是否存在内存泄露时,需要获取程序中各个模块的
内存申请调试信息,因此,为了便于对这些内存申请调试信息进行区分和管理,本发明实施
例为程序中不同的模块进行了编号,每个模块在申请内存时,其内存申请调试信息都与模
块编号相对应。具体的,在对程序进行内存泄露检测时,可以在程序中开启内存泄露检测机
制的开关,此时程序开始运行,当运行至内存申请函数被调用时,通过预先给内存申请函数
注册的钩子函数,开始调用内存泄露检测函数。该内存泄露检测函数在程序中各个模块申
请内存时记录并保存内存申请调试信息,记录并保存的内存申请调试信息包括申请内存的
首地址、模块编号、申请内存的大小以及栈信息,这些信息都是相关联的,统称为一个节点。
模块每申请一次内存的内存申请调试信息,都会被内存泄露检测函数记录,并以节点的形
式保存在一个全局结构中。然而,在模块申请内存并使用内存以后,不存在内存泄露的模块
会对申请的内存进行释放,因此该内存泄露检测函数同样能够获取到释放内存对应的内存
申请调试信息,并会在保存有内存申请调试信息的全局结构中将释放内存对应的内存申请
调试信息进行删除。具体在删除时,是依据释放内存的首地址,在全局结构中查找与释放内
存的首地址相同的内存申请调试信息,并将其删除。

由上可知,当程序运行一段时间后关闭内存泄露检测机制的开关,此时内存泄露
检测函数在全局结构中保存的内存申请调试信息就是未释放内存的内存申请调试信息,该
内存申请调试信息中的模块编号就是未释放内存的模块编号。

由于在编写模块函数的过程中,根据业务需要或者某些特殊的要求,需要在特定
条件下才会对申请的内存进行释放。例如在申请内存后经过3个小时后释放内存,但是在对
程序进行内存泄露检测的过程中,该模块申请的内存无法被释放,在这种特殊的情况下,内
存泄露检测函数同样会将这类模块的内存申请调试信息进行记录。因此,在最终确定存在
内存泄露的模块时,这类特殊的模块就会导致大量的误报。为了避免上述问题的发生,本发
明实施例在上述实施方式的基础上,可以根据特定条件下进行内存释放的函数特点对内存
泄露检测函数预先进行配置,禁止将特定条件下进行内存释放的内存申请调试信息保存在
全局结构中。

当开启程序的内存泄露检测机制的开关运行一段时间后,再关闭内存泄露检测机
制的开关,并将内存泄露检测函数保存的内存申请调试信息进行输出后,这些信息中会包
含许多不同的模块编号及其栈信息。由于同一个模块可能多次申请内存,或者在不同的内
存申请函数位置申请内存,因此这些模块编号中会存在许多相同的模块编号,并且相同的
模块编号也可能存在不同的统一内存申请框架下。因此为了准确的查找到存在内存泄露的
模块,就需要先确定统一内存申请框架。

进一步的,在上述实施例的实施方式中,是以内存泄露检测函数记录的未释放内
存的模块编号及其对应的栈信息,确定同一个统一内存申请框架下的模块(根据程序中可
被调用的内存申请函数的数量多少,可以确定多个统一内存申请框架,也可以确定一个统
一内存申请框架),并在同一个统一内存申请框架下,将未释放内存的数量最多的模块编号
所对应的模块确定为存在内存泄露的可疑模块。当确定出存在多个统一内存申请框架时,
在每个统一内存申请框架下,都可以确定出一个存在内存泄露的可疑模块,有多少个统一
内存申请框架,就可以确定出多少个存在内存泄露的可疑模块。

由于本发明实施例在对程序进行内存泄露检测时,主要是为了确定最为可能存在
内存泄露的可疑模块,因此对于确定出多个统一内存申请框架的情况而言,本发明实施例
还提供了另一种可选的实施方式,该实施方式需要在确定出的多个统一内存申请框架中,
找到最为可能存在内存泄露的可疑统一内存申请框架。具体操作为:在多个统一内存申请
框架下,分别统计每个统一内存申请框架下的未释放内存的内存申请调试信息的数量,也
就是未释放内存的节点的数量,将未释放内存的节点数量最多的统一内存申请框架确定为
存在内存泄露的可疑统一内存申请框架;进一步的,在存在内存泄露的可疑统一内存申请
框架下,将未释放内存的数量最多的模块编号所对应的模块确定为存在内存泄露的可疑模
块。例如,当根据栈信息确定了三个统一内存申请框架A、B、C后,分别统计出统一内存申请
框架A中的未释放内存的内存申请调试信息(未释放内存的节点)数量为13(其中有3个节点
是模块编号1未释放的,4个节点是模块编号2未释放的,6个节点是模块编号3未释放的);统
一内存申请框架B中的未释放内存的内存申请调试信息(未释放内存的节点)数量为11(其
中有2个节点是模块编号1未释放的,6个节点是模块编号3未释放的,3个节点是模块编号4
未释放的);统一内存申请框架C中的未释放内存的内存申请调试信息(未释放内存的节点)
数量为8(其中有3个节点是模块编号2未释放的,5个节点是模块编号1未释放的);则可以将
未释放内存的节点数量最多的统一内存申请框架A确定为存在内存泄露的可疑统一内存申
请框架;进一步的,在可疑统一内存申请框架A中,将产生未释放内存的节点数量最多的模
块编号3(具有6个)所对应的模块确定为存在内存泄露的可疑模块。

上述可选的实施方式与分别在每一个统一内存申请框架下都确定出一个可疑模
块的唯一区别在于,该可选的实施方式在确定可疑模块时,具有先后顺序,也就是最先从最
为可能存在内存泄露的统一内存申请框架下,找到可疑模块。这种查找可疑模块的方式具
有更高的精准度,能够尽可能迅速的找到存在内存泄露的可疑模块。

通过以上实施方式只是能够确定存在内存泄露的可疑模块,但是由于程序中的不
同模块代表不同的模块函数,也具有大量的代码,因此即使确定了可疑模块之后,也无法确
定该模块函数中存在内存泄露的具体代码位置。若通过人工逐行检测代码去检测则不现
实。因此,本发明实施例在确定出存在内存泄露的可疑模块之后,还需要进一步确定可疑模
块中存在内存泄露的代码位置。

具体的,在从可疑模块中确定存在内存泄露的代码位置时,可以运用到断点。断点
是用来调试程序的,当在程序中的某个位置挂载断点时,若程序运行到该位置就会暂停,此
时就可以查看程序执行到该位置时的执行情况,变化结果等,并且从断点返回时,程序还能
够正常运行下去。因此,本发明实施例可以根据可疑模块对应的模块编号及其栈信息,在对
应的内存申请函数位置挂载断点(例如GDB断点),本发明实施例中,可以在内存申请函数位
置挂载第一条件断点,所述第一条件断点用于在程序中的可疑模块调用内存申请函数申请
内存时暂停程序,使得程序运行至内存申请函数位置时暂停运行;此时,获取通过内存申请
函数申请内存的首地址。进一步的,由于模块申请内存时是为了使用内存,因此本发明实施
例还需要查看模块在申请的内存上的写操作。此时,还需要再一次利用条件断点,也就是在
申请内存的首地址挂载第二条件断点以便监听所述申请内存的首地址的写操作;当在模块
申请的内存的首地址挂载第二条件断点之后继续运行程序,当申请内存的首地址存在写操
作时停止运行程序;此时程序运行时停止的代码位置,就是所述可疑模块在写操作后没有
释放内存的位置,也就是存在内存泄露的可疑代码位置。准确的说,在程序运行停止时的代
码位置的附近区域是存在内存泄露的可疑代码位置。

当确定可疑模块的可疑代码位置之后,本发明实施例还可以进一步根据可疑模块
的函数功能和/或流程,来确定可疑模块是否为使用内存后无法释放内存的模块。例如,有
些可疑模块可能是不存在释放内存的代码,而有些可疑模块可能是将释放内存的代码编写
错误,或者有些可疑模块编写的是有条件的释放内存的代码。

在本发明实施例中,当通过栈信息确定统一内存申请框架,并在统一内存申请框
架下根据模块编号的数量确定了存在内存泄露的可疑模块之后,进一步的还可以根据断点
来找到可疑模块存在内存泄露的具体代码位置。此外,对于内存泄露检测函数记录的统一
内存申请框架下的其他模块,也可以通过挂载断点的方式依次进行检测,直至内存泄露检
测函数获取的未释放内存的内存申请调试信息中的所有模块都检测完毕为止。

进一步的,作为对上述图1所示方法的实现,本发明实施例提供了一种内存泄漏调
试装置,如图2所示,该装置包括:调用单元21、获取单元22、第一确定单元23以及第二确定
单元24,其中,

调用单元21,用于在内存申请函数被调用时,调用内存泄露检测函数,其中程序中
的不同模块通过调用所述内存申请函数申请内存;

获取单元22,用于通过执行所述内存泄露检测函数获取未释放内存的内存申请调
试信息,所述内存申请调试信息包括申请内存的模块编号及其对应的申请内存的栈信息;
这些内存申请调试信息包括:模块编号、申请内存的首地址、申请内存的大小以及栈信息;
其中,为了在程序运行过程中对程序中的各个模块进行有效区分,本发明实施例对不同的
模块分配了不同的编号;而栈信息则记录了各个模块编号对应的模块在调用内存申请函数
时的函数地址、函数参数、函数内的局部变量等;

第一确定单元23,用于将栈信息相同的模块确定为处于同一个统一内存申请框架
下的模块;其中,根据栈信息确定的统一内存申请框架可以具有多个,每个统一内存申请框
架下各个模块申请的内存只能被该框架下的各个模块使用。

第二确定单元24,用于在同一个统一内存申请框架下,将未释放内存的数量最多
的模块编号所对应的模块确定为存在内存泄露的可疑模块。

进一步的,由于第一确定单元23确定的统一内存申请框架可以具有多个,因此为
了更加快速准确的找到最为可能存在内存泄露的可疑模块,就需要先确定最为可能存在内
存泄露的可疑统一内存申请框架,因此如图3所示,所述装置还包括:

第三确定单元25,用于在第一确定单元23将栈信息相同的模块确定为处于同一个
统一内存申请框架下的模块之后,在多个统一内存申请框架下,统计每个统一内存申请框
架下的未释放内存的内存申请调试信息,将未释放内存的内存申请调试信息最多的统一内
存申请框架确定为存在内存泄露的可疑统一内存申请框架;

第二确定单元24用于在第三确定单元25确定的存在内存泄露的可疑统一内存申
请框架下,将未释放内存的数量最多的模块编号所对应的模块确定为存在内存泄露的可疑
模块。

进一步的,由于程序中的不同模块代表不同的模块函数,也具有大量的代码,因此
即使确定了可疑模块之后,也无法确定该模块函数中存在内存泄露的具体代码位置,而通
过人工逐行检测代码去检测则不现实。因此,如图3所示,所述装置还包括:

第一处理单元26,用于在将未释放内存的数量最多的模块编号所对应的模块确定
为存在内存泄露的可疑模块之后,根据可疑模块对应的模块编号,在内存申请函数位置挂
载第一条件断点,使得程序运行至内存申请函数位置时暂停运行;其中,所述第一条件断点
用于在程序中的可疑模块调用内存申请函数申请内存时暂停程序;

第二处理单元27,用于在程序暂停运行时获取申请内存的首地址,在申请内存的
首地址挂载第二条件断点以便监听所述申请内存的首地址的写操作;

在申请内存的首地址挂载第二条件断点后继续运行程序;

停止单元28,用于当所述申请内存的首地址存在写操作时停止运行程序;

第四确定单元29,用于将程序运行停止时的代码位置确定为所述可疑模块存在内
存泄露的可疑代码位置。

进一步的,为了明确可疑模块在可疑代码位置是由于什么原因导致的内存无法释
放,因此如图3所示,所述装置还包括:

第五确定单元30,用于在将程序运行停止时的代码位置确定为所述可疑模块存在
内存泄露的可疑代码位置之后,根据所述可疑模块的函数功能和/或流程,确定所述可疑模
块是否为使用内存后无法释放内存的模块。

进一步的,为了更加全面的确定内存泄露检测函数保存的内存申请调试信息中的
模块是否存在使用内存后无法释放内存的情况,因此如图3所示,所述装置还包括:

轮询单元31,用于对内存泄露检测函数获取的未释放内存的内存申请调试信息中
的所有模块编号所对应的模块进行检测,确定是否存在使用内存后无法释放内存的模块。

进一步的,所述内存申请调试信息还包括申请内存的首地址;如图3所示,获取单
元22包括:

保存模块221,用于通过执行所述内存泄露检测函数记录已申请内存的内存申请
调试信息,并将其保存在全局结构中;

删除模块222,用于当所述内存泄露检测函数检测到内存释放时,将已申请内存的
首地址与释放内存的首地址相同的内存申请调试信息从全局结构中删除。

进一步的,由于在编写模块函数的过程中,根据业务需要或者某些特殊的要求,需
要在特定条件下才会对申请的内存进行释放。因此,在最终确定存在内存泄露的模块时,这
类特殊的模块就会导致大量的误报。为了避免上述问题,如图3所示,获取单元22还包括:

配置模块223,用于根据特定条件下进行内存释放的函数特点对内存泄露检测函
数预先进行配置,禁止将特定条件下进行内存释放的内存申请调试信息保存在全局结构
中。

进一步的,为了在程序申请内存的时候获取其内存申请调试信息,因此需要在程
序中的模块调用内存申请函数时,对其申请信息进行记录,因此如图3所示,调用单元21包
括:

注册模块211,用于预先注册内存申请函数的钩子函数;

调用模块212,用于在内存申请函数被调用时通过所述钩子函数调用内存泄露检
测函数。

本发明实施例提供的一种内存泄漏调试装置,通过为程序中的不同模块进行编
号,并利用内存泄露检测函数记录模块申请内存时的栈信息来确定统一内存申请框架,最
后根据统一内存申请框架下未释放内存的数量最多的模块编号所对应的模块确定最为可
能存在内存泄露的模块。本发明避免了现有的内存泄露调试工具在统一内存申请的情况
下,定位的都是统一内存申请的位置,而不能区分到底是哪个模块没有释放内存的缺陷。

此外,本发明实施例提供的内存泄漏调试装置在定位到存在内存泄露的可疑模块
之后,还可以通过断点准确定位到可疑模块存在内存泄露的具体代码位置,不需要人工进
行逐行逐句的代码检查,提高了内存泄露查找的效率;并且针对有条件的内存释放情况,通
过预先配置内存泄露检测函数而不对特殊条件下的内存申请调试信息进行保存,使得处理
过程中占用资源较少,并且减少了误报率。

在上述实施例中,对各个实施例的描述都各有侧重,某个实施例中没有详述的部
分,可以参见其他实施例的相关描述。

可以理解的是,上述方法及装置中的相关特征可以相互参考。另外,上述实施例中
的“第一”、“第二”等是用于区分各实施例,而并不代表各实施例的优劣。

所属领域的技术人员可以清楚地了解到,为描述的方便和简洁,上述描述的系统,
装置和单元的具体工作过程,可以参考前述方法实施例中的对应过程,在此不再赘述。

在此提供的算法和显示不与任何特定计算机、虚拟系统或者其它设备固有相关。
各种通用系统也可以与基于在此的示教一起使用。根据上面的描述,构造这类系统所要求
的结构是显而易见的。此外,本发明也不针对任何特定编程语言。应当明白,可以利用各种
编程语言实现在此描述的本发明的内容,并且上面对特定语言所做的描述是为了披露本发
明的最佳实施方式。

在此处所提供的说明书中,说明了大量具体细节。然而,能够理解,本发明的实施
例可以在没有这些具体细节的情况下实践。在一些实例中,并未详细示出公知的方法、结构
和技术,以便不模糊对本说明书的理解。

类似地,应当理解,为了精简本公开并帮助理解各个发明方面中的一个或多个,在
上面对本发明的示例性实施例的描述中,本发明的各个特征有时被一起分组到单个实施
例、图、或者对其的描述中。然而,并不应将该公开的方法解释成反映如下意图:即所要求保
护的本发明要求比在每个权利要求中所明确记载的特征更多的特征。更确切地说,如下面
的权利要求书所反映的那样,发明方面在于少于前面公开的单个实施例的所有特征。因此,
遵循具体实施方式的权利要求书由此明确地并入该具体实施方式,其中每个权利要求本身
都作为本发明的单独实施例。

本领域那些技术人员可以理解,可以对实施例中的设备中的模块进行自适应性地
改变并且把它们设置在与该实施例不同的一个或多个设备中。可以把实施例中的模块或单
元或组件组合成一个模块或单元或组件,以及此外可以把它们分成多个子模块或子单元或
子组件。除了这样的特征和/或过程或者单元中的至少一些是相互排斥之外,可以采用任何
组合对本说明书(包括伴随的权利要求、摘要和附图)中公开的所有特征以及如此公开的任
何方法或者设备的所有过程或单元进行组合。除非另外明确陈述,本说明书(包括伴随的权
利要求、摘要和附图)中公开的每个特征可以由提供相同、等同或相似目的的替代特征来代
替。

此外,本领域的技术人员能够理解,尽管在此所述的一些实施例包括其它实施例
中所包括的某些特征而不是其它特征,但是不同实施例的特征的组合意味着处于本发明的
范围之内并且形成不同的实施例。例如,在下面的权利要求书中,所要求保护的实施例的任
意之一都可以以任意的组合方式来使用。

本发明的各个部件实施例可以以硬件实现,或者以在一个或者多个处理器上运行
的软件模块实现,或者以它们的组合实现。本领域的技术人员应当理解,可以在实践中使用
微处理器或者数字信号处理器(DSP)来实现根据本发明实施例的发明名称(如确定网站内
链接等级的装置)中的一些或者全部部件的一些或者全部功能。本发明还可以实现为用于
执行这里所描述的方法的一部分或者全部的设备或者装置程序(例如,计算机程序和计算
机程序产品)。这样的实现本发明的程序可以存储在计算机可读介质上,或者可以具有一个
或者多个信号的形式。这样的信号可以从因特网网站上下载得到,或者在载体信号上提供,
或者以任何其他形式提供。

应该注意的是上述实施例对本发明进行说明而不是对本发明进行限制,并且本领
域技术人员在不脱离所附权利要求的范围的情况下可设计出替换实施例。在权利要求中,
不应将位于括号之间的任何参考符号构造成对权利要求的限制。单词“包含”不排除存在未
列在权利要求中的元件或步骤。位于元件之前的单词“一”或“一个”不排除存在多个这样的
元件。本发明可以借助于包括有若干不同元件的硬件以及借助于适当编程的计算机来实
现。在列举了若干装置的单元权利要求中,这些装置中的若干个可以是通过同一个硬件项
来具体体现。单词第一、第二、以及第三等的使用不表示任何顺序。可将这些单词解释为名
称。

一种内存泄漏调试方法及装置.pdf_第1页
第1页 / 共16页
一种内存泄漏调试方法及装置.pdf_第2页
第2页 / 共16页
一种内存泄漏调试方法及装置.pdf_第3页
第3页 / 共16页
点击查看更多>>
资源描述

《一种内存泄漏调试方法及装置.pdf》由会员分享,可在线阅读,更多相关《一种内存泄漏调试方法及装置.pdf(16页珍藏版)》请在专利查询网上搜索。

本发明公开了一种内存泄漏调试方法及装置,涉及计算机技术领域,主要目的在于解决在统一内存申请的情况下无法对造成内存泄漏的代码模块进行定位的问题。本发明的方法包括:在内存申请函数被调用时,调用内存泄露检测函数,其中程序中的不同模块通过调用所述内存申请函数申请内存;通过执行所述内存泄露检测函数获取未释放内存的内存申请调试信息,所述内存申请调试信息包括申请内存的模块编号及其对应的申请内存的栈信息;将栈信息。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 物理 > 计算;推算;计数


copyright@ 2017-2020 zhuanlichaxun.net网站版权所有
经营许可证编号:粤ICP备2021068784号-1