一种航管训练系统开发中Qt程序内存使用静态检查方法

文档序号:6638533阅读:224来源:国知局
一种航管训练系统开发中Qt程序内存使用静态检查方法
【专利摘要】本发明公开了一种航管训练系统开发中Qt程序内存使用静态检查方法。在航管训练系统中运行一个Qt程序内存使用的静态检查程序,运行时将被检查的代码所在的目录作为运行参数。检测在5个模块中进行:遍历工程目录和子目录下的所有.cpp和.h文件,全路径保存为string类型存放到cpp_file中;按行读取文件每行信息,解析new和delete语句,得到Qt控件对象的创建信息和所有对象的删除信息;解析得到的Qt对象的创建信息存放在newOBJMap中,删除信息存放在deleteOBJMap中;遍历newOBJMap中的每个元素,在deleteOBJMap中查找对应的元素,存在对应元素将信息合并存放QtObjectMap中,检测结果输出到日志文件或控制台。有效解决了航管训练系统因Qt特殊性带来的内存泄露问题,大幅提高系统安全性、可靠性和实用性。
【专利说明】一种航管训练系统开发中Qt程序内存使用静态检查方法 一、 所属【技术领域】
[0001] 本发明涉及航管训练系统,特别涉及使用Qt开发的航管系统用户界面程序的内 存使用静态检查。 二、

【背景技术】
[0002] 航管训练系统除了仿真核心程序以外,还需要大量用户界面程序完成数据准备、 模拟飞行员操作、受训管制员席位等。在大型的航管训练系统进行长时间的、复杂流程的训 练活动时,对人机界面的稳定运行提出了较高的要求,如不能出现内存泄露、不能中途异常 退出等。本方法对使用QT开发的人机界面进程的源码提供静态检查机制,方便开发人员检 查错误,及时修正缺陷。
[0003] Qt是1991年由奇趣科技开发的跨平台C++图形用户界面应用程序开发框架,Qt 库中很多类都以QObject作为他们的基类,QObject的对象总是以树状结构组织自己。当 我们创建一个QObject对象时,可以指定其父对象(也被称为父控件),新创建的对象将被 加入到父对象的子对象(也被称为子控件)列表中。当父对象被析构时,这个列表中的所 有对象会被析构。不但如此,当某个QOb ject对象被析构时,它会将自己从父对象的列表中 删除,以避免父对象被析构时再次析构自己。
[0004] 由于QObject对象具有上述析构功能,当我们使用new操作符在堆中创建Qobject 对象时,并不需要使用delete操作符析构它们。
[0005] 所以编写Qt程序时,开发人员很容易写出内存处理不适当的程序导致内存泄露。 三、


【发明内容】

[0006] 本发明的目的旨在解决航管训练系统开发中使用Qt开发人机界面中,由于Qt程 序特殊性可能带来的内存泄露问题。
[0007] 本发明的目的是这样达到的:一种航管训练系统开发中Qt程序内存静态检查方 法,其特征在于:在航管训练系统中运行一个Qt程序内存使用静态的检查程序,该程序运 行时将被检查的代码所在的目录作为运行参数,目录可以有子目录,得到检测结果后,将 监测结果输出到日志文件或控制台。
[0008] 本方法专门针对Qt程序中两种Qt专属的两种内存泄露情况提供检查能力:Qt控 件对象没有父控件,在堆中new 了这个对象;Qt控件对象有父控件。
[0009] 检测在如下5个模块中进行:
[0010] 1)、遍历工程目录和子目录下的所有后缀名为· CPP和· h文件,把文件全路径保存 为string类型,再存放到vector类型的cpp_file中;
[0011] 2)、遍历cpp_file中的每个文件,按行读取文件每行信息,解析new和delete语 句,得到Qt控件对象的创建信息和所有对象的删除信息;
[0012] 3)、解析得到的Qt控件对象的创建信息存放在newOBJMap中,所有对象的删除信 息存放在deIeteOBJMap中;
[0013] 4)、遍历newOBJMap中的每个元素,在deleteOBJMap中查找对应的元素,如果存在 对应元素,则将信息合并,存放在QtObjectMap中;
[0014] 5)、遍历QtObjectMap中每个元素,得到检测结果,输出到日志文件或控制台。
[0015] 所述在1)模块中进行的检测,是通过Windows系统提供的_findfirst ()和_ findnext ()函数遍历某个工程文件下的所有文件,并把.h和.cpp文件全路径名存放在一个 Vector类型的cpp_file中,具体步骤是:
[0016] 开始,第一步,控制台获取工程目录,第二步,判断findfrist获取当前目录下第一 个实例句柄,句柄值为-IL ?是,结束,否,第三步,findnext根据_findfirst获得的句柄遍历 目录下的所有实例,判断返回值是否为〇 ?是,结束,否,进入第四步,判断此实例为子文件 夹吗?是,当前目录链接文件夹名字得到新的目录,返回第二步,否,进入第五步,判断此实 例为· cpp或· h文件吗?是,第六步,将· cpp和· h文件的全名保存到vector类型的cpp_ file中,返回第三步。
[0017] 所述在模块2)中进行的检测具体步骤是:
[0018] 开始,第一步,判断文件结束?是,结束,否,第二步,读取每行文本,保存在string 类型的line中,第三步,判断line为注释吗?是,结束,否,进入第四步,判断是line为new 或delete语句?否,进入第五步,判断是new语句?是,解析line得到的删除对象信息,文 件位置更信息,并将得到的信息保存在deleteOBJMap中,返回第一步;是new语句,进入第 六步,解析语句获得创建对象的类别,第七步,根据类别判断为Qt空间类?不是,结束,是, 第八步,将解析得到的Qt控件,父控件,文件位置信息保存到newOBJMap中,返回第一步。
[0019] 所述在模块4)中进行的检测具体步骤是:
[0020] 开始,第一步,判断newOBJMap结束?是,结束,否,第二步,获取newOBJMap的下一 元素,第三步,判断在deleteOBJMap中找到对应元素?是,第四步,将这两个元素合并,保 存到QtObjectMap,结束;否,把newOBJMap信息保存到QtObjectMap中,无删除信息补空, 回复到第一步。
[0021] 所述在模块2)进行的检测具体步骤中第三步,判断line是否为注释识别对象分 为两种://行注释,/**/段注释,注释和代码区别对待,设置一个bool变量result区别该 行代码是不是注释即可,Result由解析代码的函数返回值更新;
[0022] 若为行注释,直接跳过该行即可,并设result为commentEnd,表示注释结束;若为 段注释,且没有在一行中同时出现/*和*/,则result值为commentBegin,表示注释开始; 若在一行中同时出现/*和*/,则result值为commentEnd,表示注释结束;
[0023] 解析每行代码时,根据result值选择不同的解析函数,parseCommentO为解析注 释的函数,ParseCodeO为解析代码的函数;
[0024] 第七步中,根据类别判断为Qt空间类识别对象时分为两步:
[0025] (1)识别出程序中创建对象的语句;
[0026] (2)判断识别出的对象是不是Qt对象:Qt控件所属的类都是有继承关系的,且最 终的父对象都为QWidget,针对这种继承树的关系,通过读取InheritTree. ini配置文件建 立一个树的结构,树结构提供了一个接口:findChild(string key,P0INTER*p),返回值为指 针p指向树中关键字为key的结点,如果树中不存在关键字为key的结点,则p的值为NULL, 把某个类名作为实参传给key,可判断此类是不是Qt的控件类了,即能判断对象的对象是 不是Qt控件对象。
[0027] 本发明的积极效果是:有效解决了航管训练系统开发中,使用Qt开发人机界面 时,因 Qt特殊性可能带来的内存泄露问题,保证系统的安全。由于本发明方法检测后得到 的结果,输出到日志文件或控制台,开发人员可及时方便地发现问题,及时修正缺陷。对提 高航管训练系统自身的可靠性和实用性有非常现实的积极意义。 四、

【专利附图】

【附图说明】
[0028] 图1是本发明Qt程序内存使用静态检测软件模块组成图。
[0029] 图2是在模块扫描工程所有· cpp和· h文件流程图。
[0030] 图3是读inheritTree. ini配置文件生成Qt控件类的继承树示意图。
[0031] 图4是解析每个文件流程图。
[0032] 图 5 是合并 newOBJMap 和 deIeteOBJMap 流程图。 五、

【具体实施方式】
[0033] 本发明专门针对航管训练系统开发中使用Qt进行人机界面开发的程序进行静态 检查而研究的新方法,解决Qt程序开发中产生的内存泄露问题。
[0034] 技术实现的总思路是专门针对Qt开发中两种Qt专属的两种内存泄露情况提供检 查能力:
[0035] 本方法专门针对Qt开发中两种Qt专属的两种内存泄露情况提供检查能力:
[0036] Qt控件对象若没有父控件,如果在堆中new 了这个对象,那么必须编码实现删除, 否则会有内存泄露;
[0037] Qt控件对象有父控件,此时无需程序员手动delete这个Qt控件,因为父控件在析 构时,会自动析构自己的子控件列表里的控件,这是Qt提供的自动内存机制,而程序员可 能误写删除代码,造成内存泄露。
[0038] 除此之外还有其他属于C++语言使用的中内存泄露和冗余delete的情况,该方法 没有涉及这些情况的检测。
[0039] 本方法由几个模块组成,如图1所示。
[0040] 在模块1中,通过Windows系统提供的_findfirst()和_1^(111611:〇函数遍历工程目 录和子目录下的所有.cpp和.h文件,把文件全路径保存为string类型,再存放到vector 类型的cpp_file中。
[0041] 具体步骤是见附图2:
[0042] 开始,第一步,控制台获取工程目录,第二步,判断findfrist获取当前目录下第一 个实例句柄,句柄值为-IL ?是,结束,否,第三步,,findnext根据_findfirst获得的句柄遍历 目录下的所有实例,判断返回值是否为〇 ?是,结束,否,进入第四步,判断此实例为子文件 夹吗?是,当前目录链接文件夹名字得到新的目录,返回第二步,否,进入第五步,判断此实 例为· cpp或· h文件吗?是,将· cpp和· h文件的全名保存到vector类型的cpp_file中, 返回第三步。
[0043] 在模块2中,遍历cppjile中的每个文件,按行读取文件每行信息,解析new和 delete语句,得到Qt控件对象的创建信息和所有对象的删除信息。
[0044] 解析文件中的new和delete语句时,对于某一文件,用getLineO获取文件中的 每一行代码。
[0045] 解析过程见图4,具体步骤是:
[0046] 开始,第一步,判断文件结束?是,结束,否,第二步,读取每行文本,保存在string 类型的line中,第三步,判断line为注释吗?是,结束,否,进入第四步,判断是line为new 或delete语句?否,进入第五步,判断是new语句?是,解析line得到的删除对象信息,文 件位置更信息,并将得到的信息保存在deleteOBJMap中,返回第一步;是new语句,进入第 六步,解析语句获得创建对象的类别,第七步,根据类别判断为Qt空间类?不是,结束,是, 第八步,将解析得到的Qt控件,父控件,文件位置信息保存到newOBJMap中,返回第一步。
[0047] 对于识别注释部分和非注释部分:
[0048] 注释分两种//行注释,/**/段注释,注释和代码是要区别对待的,设置一个bool 变量result区别该行代码是不是注释即可。Result由解析代码的函数返回值更新。
[0049] 若为行注释,直接跳过该行即可,并设result为commentEnd(表示注释结束)。若 为段注释,且没有在一行中同时出现/*和*/,则result值为commentBegin (表示注释开 始)。若在一行中同时出现/*和*/,则result值为commentEnd(表示注释结束)。
[0050] 解析每行代码时,根据result值选择不同的解析函数parseCo_ent ()(解析注释 的函数),parseCode ()(解析代码的函数)。
[0051] 对于识别QT控件对象分为两步:
[0052] (1)识别出程序中创建对象的语句
[0053] 通过对Qt程序的了解,创建Qt控件对象一般是这种结构。
[0054] 例如:
[0055] QPushButon m_button = new QPushButton(Parent);
[0056] 此行代码最有标志性的词就是new和'=' 了,并且应该是一个独立的new这个关 键字,要排除***new***这种情况。
[0057] 首先,要从这行代码中获取的信息是:对象名(m_button),类名(QPushButton), 父对象(parent)。
[0058] 思路是通过"=","new","来获取每个标识符的begin(第一个字符在整行 string中的索引),end (最后一个字符在整行string中的索引)。然后通过begin和end 即可获得每个标示符。
[0059] C++中string类提供了很多接口可以直接使用。Substr (begin, Ien)用来截取子 串,find( "arg")用来寻找索引值,这两个函数的配合使用可完成上述功能。
[0060] (2)判断识别出的对象是不是Qt控件对象
[0061] 考虑到要识别所有的Qt控件对象,是一个繁杂的工作,所以只是找了一些常用的 Qt控件对象,以供识别。但是这不是固定的,如果有新的需要的话,可以在InheritTree. ini配置文件里手动添加新的对象。
[0062] Qt控件所属的类都是有继承关系的,且最终的父对象都为QWidget,针对这种继 承树的关系,建立了一个树的结构,树结构的建立是通过读取InheritTree. ini配置文件 建立的。
[0063] InheritTree. ini 文件结构不例:
[0064] [树的高度]
[0065] depthNum = η
[0066] [高度 0]
[0067] NodeNum = 1//当前高度下结点数目
[0068] QWidget = NULL//等号左边是空间类,右边是起父类
[0069] [高度 1]
[0070]
[0071] [高度 n-1]
[0072]
[0073] 树结构提供了 一个接口,findChild (std: : string key,,TreeNodePointer*p),入 口参数string key,返回值为TreeNodePointer*p,返回值是指针p指向树中关键字为key 的结点,如果树中不存在关键字为key的结点,则p的值为NULL。这个结构能判断树中是 否存在关键字为key的结点。因此,把某个类名作为实参传给key,就可判断此类是不是Qt 的控件类了,也就能判断对象的对象是不是QT控件对象了。这里,TreeNodePointer为数 据结构
[0074]

【权利要求】
1. 一种航管训练系统开发中Qt程序内存使用的静态检查方法,其特征在于:在航管训 练系统中运行一个QT程序内存使用静态的检查程序,该程序运行时将被检查的代码所在 的目录作为运行参数,该目录可以含有子目录,得到检测结果后,将监测结果输出到日志 文件或控制台; 本方法专门针对Qt程序中两种Qt专属的两种内存泄露情况提供检查能力:Qt控件对 象没有父控件,在堆中new了这个对象;Qt控件对象有父控件; 检测在如下5个模块中进行: 1)、遍历工程目录和子目录下的所有后缀名为.cpp和.h文件,把文件全路径保存为 string类型,再存放到vector类型的cpp_file中; 2)、遍历cpp_file中的每个文件,按行读取文件每行信息,解析new和delete语句,得 到Qt控件对象的创建信息和所有对象的删除信息; 3)、解析得到的Qt对象的创建信息存放在newOBJMap中,所有对象的删除信息存放在 deIeteOBJMap中; 4)、遍历newOBJMap中的每个元素,在deleteOBJMap中查找对应的元素,如果存在对应 元素,则将信息合并,存放在QtObjectMap中; 5)、遍历QtObjectMap中每个元素,得到检测结果,输出到日志文件或控制台。
2. 如权利要求1所述的航管训练系统开发中Qt程序内存使用静态检查方法,其特征在 于:所述在1)模块中进行的检测,是通过Windows系统提供的_findfirst()和_findnext() 函数遍历某个工程文件下的所有文件,并把.h和.cpp文件全路径名存放在一个Vector类 型cpp_file中,具体步骤是: 开始,第一步,控制台获取工程目录,第二步,判断findfrist获取当前目录下第一个实 例句柄,句柄值为-IL?是,结束,否,第三步,findnext根据_findfirst获得的句柄遍历目 录下的所有实例,判断返回值是否为〇 ?是,结束,否,进入第四步,判断此实例为子文件夹 吗?是,当前目录链接文件夹名字得到新的目录,返回第二步,否,进入第五步,判断此实例 为·cpp或·h文件吗?是,第六步,将·cpp和·h文件的全名保存到vector类型的cpp_file 中,返回第三步。
3. 如权利要求1所述的航管训练系统开发中Qt程序内存使用静态检查方法,其特征在 于: 所述在模块2)中进行的检测具体步骤是: 开始,第一步,判断文件结束?是,结束,否,第二步,读取每行文本,保存在string类 型的line中,第三步,判断line为注释吗?是,结束,否,进入第四步,判断是line为new 或delete语句?否,进入第五步,判断是new语句?是,解析line得到的删除对象信息,文 件位置更信息,并将得到的信息保存在deleteOBJMap中,返回第一步;是new语句,进入第 六步,解析语句获得创建对象的类别,第七步,根据类别判断为Qt空间类?不是,结束,是, 第八步,将解析得到的Qt控件,父控件,文件位置信息保存到newOBJMap中,返回第一步。
4. 如权利要求1所述的航管训练系统开发中Qt程序内存使用静态检查方法,其特征在 于:所述在模块4)中进行的检测具体步骤是: 开始,第一步,判断newOBJMap结束?是,结束,否,第二步,获取newOBJMap的下一元 素,第三步,判断在deleteOBJMap中找到对应元素?是,第四步,将这两个元素合并,保存 到QtObjectMap,结束;否,把newOBJMap信息保存到QtObjectMap中,无删除信息补空,回 复到第一步。
5. 如权利要求3所述的航管训练系统开发中Qt程序内存使用静态检查方法,其特征 在于:所述在模块2)进行的检测具体步骤中第三步,判断line是否为注释识别对象分为两 种://行注释,/**/段注释,注释和代码区别对待,设置一个bool变量result区别该行代 码是不是注释即可,Result由解析代码的函数返回值更新; 若为行注释,直接跳过该行即可,并设result为commentEnd,表示注释结束;若为段注 释,且没有在一行中同时出现/*和*/,则result值为commentBegin,表示注释开始;若在 一行中同时出现/*和*/,则result值为commentEnd,表示注释结束; 解析每行代码时,根据result值选择不同的解析函数,parseCo_ent()为解析注释的 函数,parseCodeO为解析代码的函数; 所述在模块2)进行的检测具体步骤第七步中,根据类别判断为Qt空间类识别对象时 分为两步: (1) 识别出程序中创建对象的语句; (2) 判断识别出的对象是不是Qt对象:Qt控件所属的类都是有继承关系的,且最终的 父对象都为QWidget,针对这种继承树的关系,通过读取InheritTree.ini配置文件建立一 个树的结构,树结构提供了一个接口:findChiId,findChiId返回值为指针p指向树中关键字 为key的结点,如果树中不存在关键字为key的结点,则p的值为NULL,把某个类名作为实 参传给key,可判断此类是不是Qt的控件类了,即能判断对象的对象是不是Qt控件对象。
6. 如权利要求5所述的航管训练系统开发中Qt程序内存使用静态检查方法, 其特征在于:所述树结构提供的接口为findChild,入口参数stringkey,返回值为 TreeNodePointer*p,这里,TreeNodePointer为数据结构
TreeNodePointer为指向一个描述树形结构节点的指针,该节点内容包括:节点内容key,该节点的子节点列表child_array,子节点个数child_num,节点的父节点parent。
【文档编号】G06F11/36GK104461890SQ201410768041
【公开日】2015年3月25日 申请日期:2014年12月12日 优先权日:2014年12月12日
【发明者】胡术, 王煜清, 唐麒麟 申请人:四川川大智胜软件股份有限公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1