CN106502880B - 一种内存泄漏调试方法及装置 - Google Patents
一种内存泄漏调试方法及装置 Download PDFInfo
- Publication number
- CN106502880B CN106502880B CN201610835054.9A CN201610835054A CN106502880B CN 106502880 B CN106502880 B CN 106502880B CN 201610835054 A CN201610835054 A CN 201610835054A CN 106502880 B CN106502880 B CN 106502880B
- Authority
- CN
- China
- Prior art keywords
- memory
- module
- application
- function
- suspicious
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Active
Links
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/36—Preventing errors by testing or debugging software
- G06F11/362—Software debugging
- G06F11/3636—Software debugging by tracing the execution of the program
Landscapes
- Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Computer Hardware Design (AREA)
- Quality & Reliability (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Debugging And Monitoring (AREA)
Abstract
本发明公开了一种内存泄漏调试方法及装置,涉及计算机技术领域,主要目的在于解决在统一内存申请的情况下无法对造成内存泄漏的代码模块进行定位的问题。本发明的方法包括:在内存申请函数被调用时,调用内存泄露检测函数,其中程序中的不同模块通过调用所述内存申请函数申请内存;通过执行所述内存泄露检测函数获取未释放内存的内存申请调试信息,所述内存申请调试信息包括申请内存的模块编号及其对应的申请内存的栈信息;将栈信息相同的模块确定为处于同一个统一内存申请框架下的模块;在同一个统一内存申请框架下,将未释放内存的数量最多的模块编号所对应的模块确定为存在内存泄露的可疑模块。
Description
技术领域
本发明涉及计算机技术领域,特别是涉及一种内存泄漏调试方法及装置。
背景技术
内存是计算机系统一种重要的公共资源,程序运行时都需要将数据存放在内存中,其作用是用于暂时存放中央处理器(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)来实现根据本发明实施例的发明名称(如确定网站内链接等级的装置)中的一些或者全部部件的一些或者全部功能。本发明还可以实现为用于执行这里所描述的方法的一部分或者全部的设备或者装置程序(例如,计算机程序和计算机程序产品)。这样的实现本发明的程序可以存储在计算机可读介质上,或者可以具有一个或者多个信号的形式。这样的信号可以从因特网网站上下载得到,或者在载体信号上提供,或者以任何其他形式提供。
应该注意的是上述实施例对本发明进行说明而不是对本发明进行限制,并且本领域技术人员在不脱离所附权利要求的范围的情况下可设计出替换实施例。在权利要求中,不应将位于括号之间的任何参考符号构造成对权利要求的限制。单词“包含”不排除存在未列在权利要求中的元件或步骤。位于元件之前的单词“一”或“一个”不排除存在多个这样的元件。本发明可以借助于包括有若干不同元件的硬件以及借助于适当编程的计算机来实现。在列举了若干装置的单元权利要求中,这些装置中的若干个可以是通过同一个硬件项来具体体现。单词第一、第二、以及第三等的使用不表示任何顺序。可将这些单词解释为名称。
Claims (16)
1.一种内存泄漏调试方法,其特征在于,所述方法包括:
在内存申请函数被调用时,调用内存泄露检测函数,其中程序中的不同模块通过调用所述内存申请函数申请内存;
通过执行所述内存泄露检测函数获取未释放内存的内存申请调试信息,所述内存申请调试信息包括申请内存的模块编号及其对应的申请内存的栈信息,所述栈信息中记录有各个所述申请内存的模块编号对应的模块在调用所述内存申请函数时的函数信息;
将栈信息相同的模块确定为处于同一个统一内存申请框架下的模块;
在同一个统一内存申请框架下,将未释放内存的数量最多的模块编号所对应的模块确定为存在内存泄露的可疑模块。
2.根据权利要求1所述的方法,其特征在于,在将栈信息相同的模块确定为处于同一个统一内存申请框架下的模块之后,所述方法还包括:
在多个统一内存申请框架下,统计每个统一内存申请框架下的未释放内存的内存申请调试信息,将未释放内存的内存申请调试信息最多的统一内存申请框架确定为存在内存泄露的可疑统一内存申请框架;
在存在内存泄露的可疑统一内存申请框架下,将未释放内存的数量最多的模块编号所对应的模块确定为存在内存泄露的可疑模块。
3.根据权利要求1或2所述的方法,其特征在于,在将未释放内存的数量最多的模块编号所对应的模块确定为存在内存泄露的可疑模块之后,所述方法还包括:
根据可疑模块对应的模块编号,在内存申请函数位置挂载第一条件断点,使得程序运行至内存申请函数位置时暂停运行;其中,所述第一条件断点用于在程序中的可疑模块调用内存申请函数申请内存时暂停程序;
在程序暂停运行时获取申请内存的首地址,在申请内存的首地址挂载第二条件断点以便监听所述申请内存的首地址的写操作;
继续运行程序,当所述申请内存的首地址存在写操作时停止运行程序;
将程序运行停止时的代码位置确定为所述可疑模块存在内存泄露的可疑代码位置。
4.根据权利要求3所述的方法,其特征在于,在将程序运行停止时的代码位置确定为所述可疑模块存在内存泄露的可疑代码位置之后,所述方法还包括:
根据所述可疑模块的函数功能和/或流程,确定所述可疑模块是否为使用内存后无法释放内存的模块。
5.根据权利要求4所述的方法,其特征在于,所述方法还包括:
对内存泄露检测函数获取的未释放内存的内存申请调试信息中的所有模块编号所对应的模块进行检测,确定是否存在使用内存后无法释放内存的模块。
6.根据权利要求1所述的方法,其特征在于,
所述内存申请调试信息还包括申请内存的首地址;
所述通过执行所述内存泄露检测函数获取未释放内存的内存申请调试信息包括:
通过执行所述内存泄露检测函数记录已申请内存的内存申请调试信息,并将其保存在全局结构变量中;
当所述内存泄露检测函数检测到内存释放时,将已申请内存的首地址与释放内存的首地址相同的内存申请调试信息从全局结构变量中删除。
7.根据权利要求6所述的方法,其特征在于,通过执行所述内存泄露检测函数获取未释放内存的内存申请调试信息包括:根据特定条件下进行内存释放的函数特点对内存泄露检测函数预先进行配置,禁止将特定条件下进行内存释放的内存申请调试信息保存在全局结构变量中。
8.根据权利要求1所述的方法,其特征在于,在内存申请函数被调用时,调用内存泄露检测函数包括:
预先注册内存申请函数的钩子函数,以便在内存申请函数被调用时通过所述钩子函数调用内存泄露检测函数。
9.一种内存泄漏调试装置,其特征在于,所述装置包括:
调用单元,用于在内存申请函数被调用时,调用内存泄露检测函数,其中程序中的不同模块通过调用所述内存申请函数申请内存;
获取单元,用于通过执行所述内存泄露检测函数获取未释放内存的内存申请调试信息,所述内存申请调试信息包括申请内存的模块编号及其对应的申请内存的栈信息,所述栈信息中记录有各个所述申请内存的模块编号对应的模块在调用所述内存申请函数时的函数信息;
第一确定单元,用于将栈信息相同的模块确定为处于同一个统一内存申请框架下的模块;
第二确定单元,用于在同一个统一内存申请框架下,将未释放内存的数量最多的模块编号所对应的模块确定为存在内存泄露的可疑模块。
10.根据权利要求9所述的装置,其特征在于,所述装置还包括:
第三确定单元,用于在第一确定单元将栈信息相同的模块确定为处于同一个统一内存申请框架下的模块之后,在多个统一内存申请框架下,统计每个统一内存申请框架下的未释放内存的内存申请调试信息,将未释放内存的内存申请调试信息最多的统一内存申请框架确定为存在内存泄露的可疑统一内存申请框架;
所述第二确定单元,用于在第三确定单元确定的存在内存泄露的可疑统一内存申请框架下,将未释放内存的数量最多的模块编号所对应的模块确定为存在内存泄露的可疑模块。
11.根据权利要求9或10所述的装置,其特征在于,所述装置还包括:
第一处理单元,用于在将未释放内存的数量最多的模块编号所对应的模块确定为存在内存泄露的可疑模块之后,根据可疑模块对应的模块编号,在内存申请函数位置挂载第一条件断点,使得程序运行至内存申请函数位置时暂停运行;其中,所述第一条件断点用于在程序中的可疑模块调用内存申请函数申请内存时暂停程序;
第二处理单元,用于在程序暂停运行时获取申请内存的首地址,在申请内存的首地址挂载第二条件断点以便监听所述申请内存的首地址的写操作;
在申请内存的首地址挂载第二条件断点后继续运行程序;
停止单元,用于当所述申请内存的首地址存在写操作时停止运行程序;
第四确定单元,用于将程序运行停止时的代码位置确定为所述可疑模块存在内存泄露的可疑代码位置。
12.根据权利要求11所述的装置,其特征在于,所述装置还包括:
第五确定单元,用于在将程序运行停止时的代码位置确定为所述可疑模块存在内存泄露的可疑代码位置之后,根据所述可疑模块的函数功能和/或流程,确定所述可疑模块是否为使用内存后无法释放内存的模块。
13.根据权利要求12所述的装置,其特征在于,所述装置还包括:
轮询单元,用于对内存泄露检测函数获取的未释放内存的内存申请调试信息中的所有模块编号所对应的模块进行检测,确定是否存在使用内存后无法释放内存的模块。
14.根据权利要求9所述的装置,其特征在于,
所述内存申请调试信息还包括申请内存的首地址;
所述获取单元包括:
保存模块,用于通过执行所述内存泄露检测函数记录已申请内存的内存申请调试信息,并将其保存在全局结构变量中;
删除模块,用于当所述内存泄露检测函数检测到内存释放时,将已申请内存的首地址与释放内存的首地址相同的内存申请调试信息从全局结构变量中删除。
15.根据权利要求14所述的装置,其特征在于,所述获取单元还包括:
配置模块,用于根据特定条件下进行内存释放的函数特点对内存泄露检测函数预先进行配置,禁止将特定条件下进行内存释放的内存申请调试信息保存在全局结构变量中。
16.根据权利要求9所述的装置,其特征在于,所述调用单元包括:
注册模块,用于预先注册内存申请函数的钩子函数;
调用模块,用于在内存申请函数被调用时通过所述钩子函数调用内存泄露检测函数。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201610835054.9A CN106502880B (zh) | 2016-09-20 | 2016-09-20 | 一种内存泄漏调试方法及装置 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201610835054.9A CN106502880B (zh) | 2016-09-20 | 2016-09-20 | 一种内存泄漏调试方法及装置 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN106502880A CN106502880A (zh) | 2017-03-15 |
CN106502880B true CN106502880B (zh) | 2019-05-17 |
Family
ID=58290902
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN201610835054.9A Active CN106502880B (zh) | 2016-09-20 | 2016-09-20 | 一种内存泄漏调试方法及装置 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN106502880B (zh) |
Families Citing this family (9)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN107102922B (zh) * | 2017-04-01 | 2020-08-07 | 北京三快在线科技有限公司 | 内存检测方法、装置及电子设备 |
CN107220537B (zh) * | 2017-05-25 | 2021-02-23 | 南京大学 | 一种程序内存布局信息泄露行为的检测方法 |
CN107908539B (zh) * | 2017-07-24 | 2020-07-17 | 平安科技(深圳)有限公司 | 一种检测应用程序内存泄露的方法、终端及计算机可读存储介质 |
CN107451054A (zh) * | 2017-07-26 | 2017-12-08 | 武汉虹信通信技术有限责任公司 | 一种用于linux环境中的内存池调试方法 |
CN108897603B (zh) * | 2018-07-03 | 2021-10-01 | 郑州云海信息技术有限公司 | 一种内存资源管理方法和装置 |
CN109933525A (zh) * | 2019-02-22 | 2019-06-25 | 深圳市吉祥腾达科技有限公司 | 一种通用的内存泄露检测方法 |
CN110457150B (zh) * | 2019-07-10 | 2023-03-21 | 锐捷网络股份有限公司 | 一种内存故障检测方法及装置 |
CN112817838A (zh) * | 2019-11-18 | 2021-05-18 | 迈普通信技术股份有限公司 | 内存泄漏信息处理方法、装置、电子设备及存储介质 |
CN111984496B (zh) * | 2020-07-16 | 2024-04-16 | 北京字节跳动网络技术有限公司 | 一种监控栈内存泄露的方法、装置、介质和电子设备 |
Family Cites Families (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN102262582A (zh) * | 2010-05-25 | 2011-11-30 | 芯讯通无线科技(上海)有限公司 | 移动终端及其内存泄露检测方法 |
TWI525543B (zh) * | 2013-11-20 | 2016-03-11 | 財團法人資訊工業策進會 | 混合式動態碼編譯裝置、方法及其服務系統 |
CN105373471B (zh) * | 2014-08-29 | 2019-05-24 | 腾讯科技(深圳)有限公司 | 用于内存泄露漏洞的检测方法和装置 |
CN105912458A (zh) * | 2016-03-28 | 2016-08-31 | 中国电力科学研究院 | 一种用于动态检测c/c++内存泄露的方法及系统 |
-
2016
- 2016-09-20 CN CN201610835054.9A patent/CN106502880B/zh active Active
Also Published As
Publication number | Publication date |
---|---|
CN106502880A (zh) | 2017-03-15 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN106502880B (zh) | 一种内存泄漏调试方法及装置 | |
CN105608000B (zh) | 获取代码覆盖率数据的方法及装置 | |
CN107111544B (zh) | 生产诊断中的历史控制流可视化 | |
TWI530783B (zh) | 軟體除錯之除錯途程 | |
CN109753806A (zh) | 服务器防护方法及装置 | |
US7530056B1 (en) | Method and system for detecting runtime defects in a program by comparing correct and incorrect runs | |
CN102422261B (zh) | 对所引起的异常的通知 | |
US20180081790A1 (en) | Test case reduction in application binary interface (abi) compatibility testing | |
CN104484223B (zh) | 一种安卓系统应用关闭方法和装置 | |
CN108459962A (zh) | 代码规范性检测方法、装置、终端设备及存储介质 | |
CN107315961A (zh) | 程序漏洞检测方法及装置、计算设备、存储介质 | |
CN105630671B (zh) | 代码覆盖率报告的生成方法及装置 | |
CN107678938A (zh) | 一种应用程序的调试方法及设备 | |
CN106844145A (zh) | 一种服务器硬件故障预警方法和装置 | |
CN105074656B (zh) | 管理并发谓词表达式的方法和装置 | |
US8683448B2 (en) | Protecting integrity of breakpoints in a software debugger | |
CN106598842A (zh) | 代码检测方法、装置及电子设备 | |
CN111221721B (zh) | 一种单元测试案例自动化录制和执行方法及装置 | |
CN107229867A (zh) | 内核漏洞挖掘方法、装置、计算设备及计算机存储介质 | |
US20080010536A1 (en) | Breakpoints with Separate Conditions | |
CN106933642A (zh) | 应用程序的处理方法及处理装置 | |
US9870306B2 (en) | Exception prediction before an actual exception during debugging | |
CN109144874A (zh) | 一种测试环境的监测方法和装置 | |
CN105912467A (zh) | 一种性能测试方法及装置 | |
JP2019160270A (ja) | 欠陥関数を検査する方法、装置、サーバ及びプログラム |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
C06 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |