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

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

摘要

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

著录项

  • 公开/公告号CN104461890A

    专利类型发明专利

  • 公开/公告日2015-03-25

    原文格式PDF

  • 申请/专利权人 四川川大智胜软件股份有限公司;

    申请/专利号CN201410768041.5

  • 发明设计人 胡术;王煜清;唐麒麟;

    申请日2014-12-12

  • 分类号G06F11/36;

  • 代理机构成都睿道专利代理事务所(普通合伙);

  • 代理人潘育敏

  • 地址 610045 四川省成都市武侯区武科东一路七号

  • 入库时间 2023-12-18 08:05:40

法律信息

  • 法律状态公告日

    法律状态信息

    法律状态

  • 2017-05-17

    授权

    授权

  • 2015-09-09

    著录事项变更 IPC(主分类):G06F11/36 变更前: 变更后: 申请日:20141212

    著录事项变更

  • 2015-09-09

    专利申请权的转移 IPC(主分类):G06F11/36 变更前: 变更后: 登记生效日:20150818 申请日:20141212

    专利申请权、专利权的转移

  • 2015-04-22

    实质审查的生效 IPC(主分类):G06F11/36 申请日:20141212

    实质审查的生效

  • 2015-03-25

    公开

    公开

说明书

一、所属技术领域

本发明涉及航管训练系统,特别涉及使用Qt开发的航管系统用户界面程序的内存使用静 态检查。

二、背景技术

航管训练系统除了仿真核心程序以外,还需要大量用户界面程序完成数据准备、模拟飞 行员操作、受训管制员席位等。在大型的航管训练系统进行长时间的、复杂流程的训练活动 时,对人机界面的稳定运行提出了较高的要求,如不能出现内存泄露、不能中途异常退出等。 本方法对使用QT开发的人机界面进程的源码提供静态检查机制,方便开发人员检查错误,及 时修正缺陷。

Qt是1991年由奇趣科技开发的跨平台C++图形用户界面应用程序开发框架,Qt库中很 多类都以QObject作为他们的基类,QObject的对象总是以树状结构组织自己。当我们创建 一个QObject对象时,可以指定其父对象(也被称为父控件),新创建的对象将被加入到父对 象的子对象(也被称为子控件)列表中。当父对象被析构时,这个列表中的所有对象会被析 构。不但如此,当某个QObject对象被析构时,它会将自己从父对象的列表中删除,以避免 父对象被析构时再次析构自己。

由于QObject对象具有上述析构功能,当我们使用new操作符在堆中创建Qobject对象 时,并不需要使用delete操作符析构它们。

所以编写Qt程序时,开发人员很容易写出内存处理不适当的程序导致内存泄露。

三、发明内容

本发明的目的旨在解决航管训练系统开发中使用Qt开发人机界面中,由于Qt程序特殊 性可能带来的内存泄露问题。

本发明的目的是这样达到的:一种航管训练系统开发中Qt程序内存静态检查方法,其特 征在于:在航管训练系统中运行一个Qt程序内存使用静态的检查程序,该程序运行时将被检 查的代码所在的目录作为运行参数,目录可以有子目录,得到检测结果后,将监测结果输出到 日志文件或控制台。

本方法专门针对Qt程序中两种Qt专属的两种内存泄露情况提供检查能力:Qt控件对象没有 父控件,在堆中new了这个对象;Qt控件对象有父控件。

检测在如下5个模块中进行:

1)、遍历工程目录和子目录下的所有后缀名为.cpp和.h文件,把文件全路径保存为 string类型,再存放到vector类型的cpp_file中;

2)、遍历cpp_file中的每个文件,按行读取文件每行信息,解析new和delete语句, 得到Qt控件对象的创建信息和所有对象的删除信息;

3)、解析得到的Qt控件对象的创建信息存放在newOBJMap中,所有对象的删除信息存 放在deleteOBJMap中;

4)、遍历newOBJMap中的每个元素,在deleteOBJMap中查找对应的元素,如果存在对 应元素,则将信息合并,存放在QtObjectMap中;

5)、遍历QtObjectMap中每个元素,得到检测结果,输出到日志文件或控制台。

所述在1)模块中进行的检测,是通过Windows系统提供的_findfirst()和_findnext() 函数遍历某个工程文件下的所有文件,并把.h和.cpp文件全路径名存放在一个Vector类型 的cpp_file中,具体步骤是:

开始,第一步,控制台获取工程目录,第二步,判断findfrist获取当前目录下第一个实 例句柄,句柄值为-1L?是,结束,否,第三步,findnext根据_findfirst获得的句柄遍历 目录下的所有实例,判断返回值是否为0?是,结束,否,进入第四步,判断此实例为子文 件夹吗?是,当前目录链接文件夹名字得到新的目录,返回第二步,否,进入第五步,判断 此实例为.cpp或.h文件吗?是,第六步,将.cpp和.h文件的全名保存到vector类型的 cpp_file中,返回第三步。

所述在模块2)中进行的检测具体步骤是:

开始,第一步,判断文件结束?是,结束,否,第二步,读取每行文本,保存在string 类型的line中,第三步,判断line为注释吗?是,结束,否,进入第四步,判断是line为 new或delete语句?否,进入第五步,判断是new语句?是,解析line得到的删除对象信 息,文件位置更信息,并将得到的信息保存在deleteOBJMap中,返回第一步;是new语句, 进入第六步,解析语句获得创建对象的类别,第七步,根据类别判断为Qt空间类?不是,结 束,是,第八步,将解析得到的Qt控件,父控件,文件位置信息保存到newOBJMap中,返 回第一步。

所述在模块4)中进行的检测具体步骤是:

开始,第一步,判断newOBJMap结束?是,结束,否,第二步,获取newOBJMap的下一 元素,第三步,判断在deleteOBJMap中找到对应元素?是,第四步,将这两个元素合并,保 存到QtObjectMap,结束;否,把newOBJMap信息保存到QtObjectMap中,无删除信息补空, 回复到第一步。

所述在模块2)进行的检测具体步骤中第三步,判断line是否为注释识别对象分为两种: //行注释,/**/段注释,注释和代码区别对待,设置一个bool变量result区别该行代码 是不是注释即可,Result由解析代码的函数返回值更新;

若为行注释,直接跳过该行即可,并设result为commentEnd,表示注释结束;若为段注 释,且没有在一行中同时出现/*和*/,则result值为commentBegin,表示注释开始;若 在一行中同时出现/*和*/,则result值为commentEnd,表示注释结束;

解析每行代码时,根据result值选择不同的解析函数,parseComment()为解析注释的函数, parseCode()为解析代码的函数;

第七步中,根据类别判断为Qt空间类识别对象时分为两步:

(1)识别出程序中创建对象的语句;

(2)判断识别出的对象是不是Qt对象:Qt控件所属的类都是有继承关系的,且最终的父对 象都为QWidget,针对这种继承树的关系,通过读取InheritTree.ini配置文件建立一个树 的结构,树结构提供了一个接口:findChild(string key,POINTER*p),返回值为指针p指 向树中关键字为key的结点,如果树中不存在关键字为key的结点,则p的值为NULL,把某 个类名作为实参传给key,可判断此类是不是Qt的控件类了,即能判断对象的对象是不是Qt 控件对象。

本发明的积极效果是:有效解决了航管训练系统开发中,使用Qt开发人机界面时,因Qt 特殊性可能带来的内存泄露问题,保证系统的安全。由于本发明方法检测后得到的结果,输 出到日志文件或控制台,开发人员可及时方便地发现问题,及时修正缺陷。对提高航管训练 系统自身的可靠性和实用性有非常现实的积极意义。

四、附图说明

图1是本发明Qt程序内存使用静态检测软件模块组成图。

图2是在模块扫描工程所有.cpp和.h文件流程图。

图3是读inheritTree.ini配置文件生成Qt控件类的继承树示意图。

图4是解析每个文件流程图。

图5是合并newOBJMap和deleteOBJMap流程图。

五、具体实施方式

本发明专门针对航管训练系统开发中使用Qt进行人机界面开发的程序进行静态检查而研 究的新方法,解决Qt程序开发中产生的内存泄露问题。

技术实现的总思路是专门针对Qt开发中两种Qt专属的两种内存泄露情况提供检查能力:

本方法专门针对Qt开发中两种Qt专属的两种内存泄露情况提供检查能力:

Qt控件对象若没有父控件,如果在堆中new了这个对象,那么必须编码实现删除,否则 会有内存泄露;

Qt控件对象有父控件,此时无需程序员手动delete这个Qt控件,因为父控件在析构时, 会自动析构自己的子控件列表里的控件,这是Qt提供的自动内存机制,而程序员可能误写删 除代码,造成内存泄露。

除此之外还有其他属于C++语言使用的中内存泄露和冗余delete的情况,该方法没有涉 及这些情况的检测。

本方法由几个模块组成,如图1所示。

在模块1中,通过Windows系统提供的_findfirst()和_findnext()函数遍历工程目录和 子目录下的所有.cpp和.h文件,把文件全路径保存为string类型,再存放到vector类型的 cpp_file中。

具体步骤是见附图2:

开始,第一步,控制台获取工程目录,第二步,判断findfrist获取当前目录下第一个实 例句柄,句柄值为-1L?是,结束,否,第三步,,findnext根据_findfirst获得的句柄遍历 目录下的所有实例,判断返回值是否为0?是,结束,否,进入第四步,判断此实例为子文 件夹吗?是,当前目录链接文件夹名字得到新的目录,返回第二步,否,进入第五步,判断 此实例为.cpp或.h文件吗?是,将.cpp和.h文件的全名保存到vector类型的cpp_file中, 返回第三步。

在模块2中,遍历cpp_file中的每个文件,按行读取文件每行信息,解析new和delete 语句,得到Qt控件对象的创建信息和所有对象的删除信息。

解析文件中的new和delete语句时,对于某一文件,用getLine()获取文件中的每一行代码。

解析过程见图4,具体步骤是:

开始,第一步,判断文件结束?是,结束,否,第二步,读取每行文本,保存在string 类型的line中,第三步,判断line为注释吗?是,结束,否,进入第四步,判断是line为 new或delete语句?否,进入第五步,判断是new语句?是,解析line得到的删除对象信 息,文件位置更信息,并将得到的信息保存在deleteOBJMap中,返回第一步;是new语句, 进入第六步,解析语句获得创建对象的类别,第七步,根据类别判断为Qt空间类?不是,结 束,是,第八步,将解析得到的Qt控件,父控件,文件位置信息保存到newOBJMap中,返 回第一步。

对于识别注释部分和非注释部分:

注释分两种//行注释,/**/段注释,注释和代码是要区别对待的,设置一个bool变量 result区别该行代码是不是注释即可。Result由解析代码的函数返回值更新。

若为行注释,直接跳过该行即可,并设result为commentEnd(表示注释结束)。若为段注释, 且没有在一行中同时出现/*和*/,则result值为commentBegin(表示注释开始)。若在一 行中同时出现/*和*/,则result值为commentEnd(表示注释结束)。

解析每行代码时,根据result值选择不同的解析函数parseComment()(解析注释的函数), parseCode()(解析代码的函数)。

对于识别QT控件对象分为两步:

(1)识别出程序中创建对象的语句

通过对Qt程序的了解,创建Qt控件对象一般是这种结构。

例如:

QPushButon m_button=new QPushButton(Parent);

此行代码最有标志性的词就是new和’=’了,并且应该是一个独立的new这个关键字,要排 除***new***这种情况。

首先,要从这行代码中获取的信息是:对象名(m_button),类名(QPushButton),父对象 (parent)。

思路是通过”=”,”new”,”()”来获取每个标识符的begin(第一个字符在整行string 中的索引),end(最后一个字符在整行string中的索引)。然后通过begin和end即可获得 每个标示符。

C++中string类提供了很多接口可以直接使用。Substr(begin,len)用来截取子串,find (“arg”)用来寻找索引值,这两个函数的配合使用可完成上述功能。

(2)判断识别出的对象是不是Qt控件对象

考虑到要识别所有的Qt控件对象,是一个繁杂的工作,所以只是找了一些常用的Qt控件对 象,以供识别。但是这不是固定的,如果有新的需要的话,可以在InheritTree.ini配置文 件里手动添加新的对象。

Qt控件所属的类都是有继承关系的,且最终的父对象都为QWidget,针对这种继承树的关系, 建立了一个树的结构,树结构的建立是通过读取InheritTree.ini配置文件建立的。

InheritTree.ini文件结构示例:

[树的高度]

depthNum=n

[高度0]

NodeNum=1//当前高度下结点数目

QWidget=NULL//等号左边是空间类,右边是起父类

[高度1]

...

[高度n-1]

...

树结构提供了一个接口,findChild(std::string key,,TreeNodePointer*p),入口 参数string key,返回值为TreeNodePointer*p,返回值是指针p指向树中关键字为key的结 点,如果树中不存在关键字为key的结点,则p的值为NULL。这个结构能判断树中是否存在 关键字为key的结点。因此,把某个类名作为实参传给key,就可判断此类是不是Qt的控件 类了,也就能判断对象的对象是不是QT控件对象了。这里,TreeNodePointer为数据结构

TreeNodePointer为指向一个描述树形结构节点的指针,该节点内容包括:节点内容key,该 节点的子节点列表child_array,子节点个数child_num,节点的父节点parent。

读inheritTree.ini配置文件生成Qt控件类的继承树参见图3。

在模块3中,解析得到的Qt控件对象的创建信息存放在newOBJMap中,所有对象的删 除信息存放在deleteOBJMap中。

删除对象语句的识别处理方式和在模块2中的识别相同,不再赘述。不过此处因为无法 得到类名,无法判断是不是Qt控件类的对象,所以把所有对象全部保存在下面提到的 deleteOBJMap中。

向deleteOBJMap和newOBJMap里添加删除和创建对象的信息,将上一步识别出的new和 delete语句中的信息保存在以下两个结构体中:

这两个结构体类型的对象分别放在newOBJMap,deleteOBJMap中。

在模块4中,遍历newOBJMap中的每个元素,在deleteOBJMap中查找对应的元素,如 果存在对应元素,则将信息合并,存放在QtObjectMap中;

合并newOBJMap和deleteOBJMap,流程参见附图5。

具体步骤是:开始,第一步,判断newOBJMap结束?是,结束,否,第二步,获取newOBJMap 的下一元素,第三步,判断在deleteOBJMap中找到对应元素?是,将这两个元素合并,保存 到QtObjectMap,结束。否,把newOBJMap信息保存到QtObjectMap中,无删除信息补空, 回复到第一步。

将delteOBJMap和newOBJMap中的信息组合到QTObjectMap中时通过循环迭代,找到 newOBJMap里的每个Qt控件对象,看delteOBJMap中是否有对应的信息,如果有,就把这两 个结构体对象里的信息整合到以下结构体中:

把此结构体对象插入到QTObjectMap中。

在模块5中,遍历QtObjectMap中每个元素,得到检测结果,输出到日志文件或控制台。 根据QTObjectMap中的信息输出检测结果,

在QTObjectMap中的每个对象QTOBJ

最后输出结果到控制台和日志文件中。

最后的结果输出到控制台和日志文件中后,有利于开发人员进行修改:

以检查E://航管训练目录下的所有文件为例,输出示例如下:

疑似内存泄露:objectName(控件对象名)E://航管训练//a.cpp(创建对象文件全目 录)600(行号);

疑似手工删除错误:objectName(控件名)parentName(父控件名)E://航管训练 //a.cpp(创建对象文件全目录)600(行号)E://航管训练//a.cpp(删除对象文件全目录) (行号)。

去获取专利,查看全文>

相似文献

  • 专利
  • 中文文献
  • 外文文献
获取专利

客服邮箱:kefu@zhangqiaokeyan.com

京公网安备:11010802029741号 ICP备案号:京ICP备15016152号-6 六维联合信息科技 (北京) 有限公司©版权所有
  • 客服微信

  • 服务号