QT核心编程之调试技术 (g)
Qt应用程序的调试可以通过DDD进行跟踪调试和打印各种调试或警告信息。DDD(Data Display Debugger)是使用gdb调试工具的图形工具,它安装在Linux操作系统中,使用方法可参考DDD的帮助文档。
QT核心编程之调试技术是本节要介绍的内容,QT核心编程我们要分几个部分来介绍,想参考更多内容,请看末尾的编辑推荐进行详细阅读,先来看本篇内容。
Qt应用程序的调试可以通过DDD进行跟踪调试和打印各种调试或警告信息。DDD(Data Display Debugger)是使用gdb调试工具的图形工具,它安装在Linux操作系统中,使用方法可参考DDD的帮助文档。下面说明如何打印各种调试或警告信息
1、命令行参数
当你运行Q应用程序时,你可以指定几个命令行参数来帮助你调试。这几个命令行参数说明如下:
-nograb 应用程序不再捕获鼠标或者键盘。当程序在Linux下运行在gdb调试器中时这个选项是默认的。
-dograb 忽略任何隐含的或明显得-nograb。即使-nograb出现在命令行的最后,-dograb也会超过-nograb生效的。
-sync 在X同步模式下运行应用程序。同步模式强迫X服务器立即执行每一个X客户端的请求,而不使用缓存优化。它使得程序更加容易测试并且通常会更慢。-sync模式只对X11版本的Qt有效。
2、打印警告和调试消息
Qt使用三个全局函数qDebug、qWarning和qFatal来打印警告和调试信息到标准错误输出stderr(它在缺省情况下为显示屏,也可指定为文件)。 这三个函数说明如下:
qDebug()用来打印调试信息,在调试版本中输出信息,在发布版本中,函数将不起作用。
qWarning()用来在程序发生错误时打印警告信息。
qFatal()用来打印致命错误消息并且退出。
这些函数的Qt实现在Unix/X11下把文本打印到标准错误输出(stderr),在Windows下会打印到调试器。你可以通过安装一个消息处理器,qInstallMsgHandler()来接收这些函数。
因为这3个函数的实现类似,这里只分析函数qDebug,qDebug函数的参数格式与函数printf类似,打印格式化字符串。qDebug函数列出如下(在src/tools/qglobal.cpp中):
- static QtMsgHandler handler = 0; //指向用户定义的打印输出函数的句柄
- static const int QT_BUFFER_LENGTH = 8196; //内部buffer长度
- void qDebug( const char *msg, ... ) //msg格式化的需要打印的字符串
- {
- char buf[QT_BUFFER_LENGTH];
- va_list ap;
- va_start( ap, msg );//使用可变的参数链表
- #if defined(QT_VSNPRINTF)
- QT_VSNPRINTF( buf, QT_BUFFER_LENGTH, msg, ap );
- #else vsprintf( buf, msg, ap ); //将需要打印的信息放入到buf中
- #endif va_end( ap );
- if ( handler ) { //如果用户指定的输出函数存在,使用它来输出信息
- (*handler)( QtDebugMsg, buf );
- } else {
- #if defined(Q_CC_MWERKS)
- mac_default_handler(buf); //mac系统下的缺省输出函数
- #elif defined(Q_OS_TEMP)
- QString fstr( buf );
- OutputDebugString( (fstr + "\n").ucs2() );
- #else fprintf( stderr, "%s\n", buf ); // 输出到stderr#endif
- }
- }
在src/tools/qglobal.h中定义了QtMsgHandler的函数类型,并将函数qInstallMsgHandler定义为从动态库中输出函数名。这两个定义列出如下:
typedef void (*QtMsgHandler)(QtMsgType, const char *);// Q_EXPORT表示动态库中输出这个函数名Q_EXPORT QtMsgHandler qInstallMsgHandler( QtMsgHandler );
函数qInstallMsgHandler被用户用来定义一个安装处理函数,并返回以前定义的消息处理函数的指针。在一个应用程序中只能定义一个消息处理函数。恢复以前的消息处理函数时,调用qInstallMsgHandler(0)。函数列出如下(在src/tools/qglobal.cpp中):
- QtMsgHandler qInstallMsgHandler( QtMsgHandler h ){
- QtMsgHandler old = handler;
- hhandler = h;
- return old;
- }
示例:应用qInstallMsgHandler
下面的例子说明如果在一个应用程序中安装自己的程序运行信息输出函数。这个例子先定义了信息输出函数myMessageOutput,然后,在程序的main函数中安装了信息输出函数。当这个应用函数运行时,就会使用函数myMessageOutput输出运行信息。代码如下:
- #include <qapplication.h>
- #include <stdio.h>
- #include <stdlib.h>
- void myMessageOutput( QtMsgType type, const char *msg )//定义信息输出函数{
- switch ( type ) {
- case QtDebugMsg: //输出调试信息
- fprintf( stderr, "Debug: %s\n", msg );
- break;
- case QtWarningMsg: //输出警告信息
- fprintf( stderr, "Warning: %s\n", msg );
- break;
- case QtFatalMsg: //输出致命信息
- fprintf( stderr, "Fatal: %s\n", msg );
- abort(); //中断运行,退出程序
- }
- }
- int main( int argc, char **argv ){
- qInstallMsgHandler( myMessageOutput ); //安装信息输出函数
- QApplication a( argc, argv );
- ...
- return a.exec();
- }
还有另外两个打印对象信息的调试函数QObject::dumpObjectTree()和QObject::dumpObjectInfo()。它们只在程序调试版本下,输出信息,在发布版本中,这两个函数不起作用。函数QObject::dumpObjectInfo()打印一个对象信号连接等方面的信息。函数QObject::dumpObjectTree()打印出子对象树。
3、调试宏
在程序运行中还常使用宏Q_ASSERT和Q_CHECK_PTR来输出信息,这两个宏说明如下:
(1)Q_ASSERT(b)中的b是一个布尔表达式,当b是FALSE的时候,打印出类似的警告信息:"ASSERT:‘b’ in file file.cpp (234)"。
(2)Q_CHECK_PTR(p)中的p是一个指针。如果p是空的话,打印出类似的警告信息:"In file file.cpp, line 234: Out of memory"。
宏Q_ASSERT实质上是调用函数qFatal或qWarning输出信息,列出如下(在src/tools/qglobal.h中):
- #if !defined(Q_ASSERT)
- # if defined(QT_CHECK_STATE)
- # if defined(QT_FATAL_ASSERT)
- # define Q_ASSERT(x) //打印x,文件名,在程序源代码中的行号
- # else
- # define Q_ASSERT(x)
- # endif
- # else
- # define Q_ASSERT(x)
- # endif#endif
宏Q_CHECK_PTR实质上调用函数qWarning输出信息,宏定义Q_CHECK_PTR列出如下(在src/tools/qglobal.h中):
- #if defined(QT_CHECK_NULL)
- # define Q_CHECK_PTR(p) (qt_check_pointer#else# define Q_CHECK_PTR(p)
- #endif Q_EXPORT bool qt_check_pointer( bool c, const char *, int );
函数qt_check_pointer实现信息输出操作,函数列出如下(在src/tools/qglobal.cpp中):
- bool qt_check_pointer( bool c, const char *n, int l ){ if ( c ) qWarning( "In file %s, line %d: Out of memory", n, l );
- return TRUE;}
示例2:运行宏Q_ASSERT和Q_ASSERT
宏Q_ASSERT和Q_ASSERT常用来检测程序错误,下面例子使用了这两个宏:
- char *alloc( int size ){
- Q_ASSERT( size > 0 ); //如果size > 0表达式不成立,打印警告信息
- char *p = new char[size];
- Q_CHECK_PTR( p ); //如果指针p为空,打印警告信息
- return p;
- }
Qt基于不同的调试标记打印不同类型的警告信息。Qt使用了下面的宏定义说明了不同的调试标记(在src/tools/qglobal.h中):
QT_CHECK_STATE:检测一致的/期望的对象状态
QT_CHECK_RANGE:检测变量范围错误
QT_CHECK_NULL:检测危险的空指针
QT_CHECK_MATH:检测危险的数学,比如被0除
QT_NO_CHECK:关闭所有的QT_CHECK_...标记
QT_DEBUG:使调试代码生效
QT_NO_DEBUG:关闭QT_DEBUG标记
默认情况下,QT_DEBUG和所有的QT_CHECK标记都是打开的。如果要关闭QT_DEBUG,请定义QT_NO_DEBUG。如果要关闭QT_CHECK标记,请定义QT_NO_CHECK。
示例3: 打印不同类型的警告信息
下面的例子根据不同的宏定义打印不同类型的警告信息。代码如下:
- void f( char *p, int i ){
- #if defined(QT_CHECK_NULL) //检测危险的空指针
- if ( p == 0 ) qWarning( "f: Null pointer not allowed" );
- #endif #if defined(QT_CHECK_RANGE) //检测变量范围错误
- if ( i < 0 )
- qWarning( "f: The index cannot be negative" );
- #endif}
小结:QT核心编程之调试技术的内容介绍完了,需要本文能对你有所帮助,需要更多资料的话,请参考编辑推荐。
QT核心编程之调试技术 (g)的更多相关文章
- QT核心编程之Qt线程 (c)
QT核心编程之Qt线程是本节要介绍的内容,QT核心编程我们要分几个部分来介绍,想参考更多内容,请看末尾的编辑推荐进行详细阅读,先来看本篇内容. Qt对线程提供了支持,它引入了一些基本与平台无关的线程类 ...
- Qt on Android 核心编程
Qt on Android 核心编程(最好看的Qt编程书!CSDN博主foruok倾力奉献!) 安晓辉 著 ISBN 978-7-121-24457-5 2015年1月出版 定价:65.00元 4 ...
- 《Qt on Android核心编程》夹
china-pub在售前,售中环节退房,折扣低! 有朋友想看看<Qt on Android核心编程>的文件夹,So-- 文件夹 <Qt on Android核心编程>文 ...
- 《Qt on Android核心编程》介绍
<Qt on Android核心编程>最终尘埃落定.付梓印刷了. 2014-11-02更新:china-pub的预售链接出来了.折扣非常低哦. 封面 看看封面的效果吧,历经几版,最终就成了 ...
- 《Qt on Android核心编程》相关资源
有不少朋友反馈在搭建 Qt on Android 开发环境时遇到了问题,诸如 Android SDK 无法下载. jdk 找不到合适的版本号.创建 AVD 出错等等.为此我把与<Qt on An ...
- windows核心编程 DLL技术 【转】
注:本文章转载于网络,源地址为:http://blog.csdn.net/ithzhang/article/details/7051558 本篇文章将介绍DLL显式链接的过程和模块基地址重定位及模块绑 ...
- 《Windows核心编程系列》二十谈谈DLL高级技术
本篇文章将介绍DLL显式链接的过程和模块基地址重定位及模块绑定的技术. 第一种将DLL映射到进程地址空间的方式是直接在源代码中引用DLL中所包含的函数或是变量,DLL在程序运行后由加载程序隐式的载入, ...
- Qt核心机制与原理
转: https://blog.csdn.net/light_in_dark/article/details/64125085 ★了解Qt和C++的关系 ★掌握Qt的信号/槽机制的原理和使用方法 ★ ...
- Qt核心机制和原理
转:http://blog.csdn.net/light_in_dark/article/details/64125085 ★了解Qt和C++的关系 ★掌握Qt的信号/槽机制的原理和使用方法 ★了解Q ...
随机推荐
- 本人为项目组制定的一份页面优化指南(easyui页面优化方案)
#本人为项目组制定的一份页面优化指南(easyui页面优化方案) ##背景 这是一篇我之前为项目组制定的页面优化指南,主要是面向表单页面,典型的像[注册用户](https://passport.cnb ...
- Windows Azure 配置多个站点的虚拟网络连接
通过上一篇"Windows Azure 虚拟网络配置(Site to Site)" 我们建立了可以进行Site to Site连接的虚拟网络,配置过后有些朋友会有疑问:如果需要连接 ...
- 转】MyEclipse使用总结——设置MyEclipse使用的Tomcat服务器
原博文出自于: http://www.cnblogs.com/xdp-gacl/p/3935499.html 感谢! 一.设置使用的Tomcat服务器 如果不想使用MyEclipse自带的tomcat ...
- 深刻理解Python中的元类metaclass(转)
本文由 伯乐在线 - bigship 翻译 英文出处:stackoverflow 译文:http://blog.jobbole.com/21351/ 译注:这是一篇在Stack overflow上很热 ...
- Options for Debugging Your Program or GCC
[Options for Debugging Your Program or GCC] -g Produce debugging information in the operating system ...
- 题目连接:http://acm.zznu.edu.cn/problem.php?id=1329
题目大意: 定理:把一个至少两位的正整数的个位数字去掉,再从余下的数中减去个位数的5倍.当且仅当差是17的倍数时,原数也是17的倍数 . 例如,34是17的倍数,因为3-20=-17是17的倍数:20 ...
- POJ3630Phone List(字典树)
经典的字典树的题目了,这次完全是按照自己的风格来写的,没有参考其他人的代码风格来写. 分析:如果采用常规的暴力枚举,那么复杂度就是O(n*n*str.length) = O(10^9),这明显是会超时 ...
- [Sparrow OS 设计文档连载(一)] Introduction
- 在Windows2012下安装SQL Server 2005无法启动服务的解决办法
下面是我亲自经历过的总结. 因为尝鲜安装了Windows2012,的确很不错,唯一的遗憾就是不支持Sql Server 2005的安装.找了很多办法,基本上都有缺陷.现在终于找到一种完全正常没有缺陷的 ...
- Java字面常量与常量池
Java中的字面常量(区别于final创建的有名常量)通常会保存在常量池中,常量池可以理解为像堆一样的内存区域.但是常量池有一个特性就是,如果常量池中已存在该常量将不会再次为该常量开辟内存 还是看个程 ...