QT核心编程之调试技术 (g)

Qt应用程序的调试可以通过DDD进行跟踪调试和打印各种调试或警告信息。DDD(Data Display Debugger)是使用gdb调试工具的图形工具,它安装在Linux操作系统中,使用方法可参考DDD的帮助文档。

AD:51CTO首届中国APP创新评选大赛正在招募>>

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中):

  1. static QtMsgHandler handler = 0;  //指向用户定义的打印输出函数的句柄
  2. static const int QT_BUFFER_LENGTH = 8196; //内部buffer长度
  3. void qDebug( const char *msg, ... ) //msg格式化的需要打印的字符串
  4. {
  5. char buf[QT_BUFFER_LENGTH];
  6. va_list ap;
  7. va_start( ap, msg );//使用可变的参数链表
  8. #if defined(QT_VSNPRINTF)
  9. QT_VSNPRINTF( buf, QT_BUFFER_LENGTH, msg, ap );
  10. #else    vsprintf( buf, msg, ap ); //将需要打印的信息放入到buf中
  11. #endif    va_end( ap );
  12. if ( handler ) {    //如果用户指定的输出函数存在,使用它来输出信息
  13. (*handler)( QtDebugMsg, buf );
  14. } else {
  15. #if defined(Q_CC_MWERKS)
  16. mac_default_handler(buf); //mac系统下的缺省输出函数
  17. #elif defined(Q_OS_TEMP)
  18. QString fstr( buf );
  19. OutputDebugString( (fstr + "\n").ucs2() );
  20. #else fprintf( stderr, "%s\n", buf );  // 输出到stderr#endif
  21. }
  22. }

在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中):

  1. QtMsgHandler qInstallMsgHandler( QtMsgHandler h ){
  2. QtMsgHandler old = handler;
  3. hhandler = h;
  4. return old;
  5. }

示例:应用qInstallMsgHandler

下面的例子说明如果在一个应用程序中安装自己的程序运行信息输出函数。这个例子先定义了信息输出函数myMessageOutput,然后,在程序的main函数中安装了信息输出函数。当这个应用函数运行时,就会使用函数myMessageOutput输出运行信息。代码如下:

  1. #include <qapplication.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. void myMessageOutput( QtMsgType type, const char *msg )//定义信息输出函数{
  5. switch ( type ) {
  6. case QtDebugMsg: //输出调试信息
  7. fprintf( stderr, "Debug: %s\n", msg );
  8. break;
  9. case QtWarningMsg: //输出警告信息
  10. fprintf( stderr, "Warning: %s\n", msg );
  11. break;
  12. case QtFatalMsg: //输出致命信息
  13. fprintf( stderr, "Fatal: %s\n", msg );
  14. abort(); //中断运行,退出程序
  15. }
  16. }
  17. int main( int argc, char **argv ){
  18. qInstallMsgHandler( myMessageOutput ); //安装信息输出函数
  19. QApplication a( argc, argv );
  20. ...
  21. return a.exec();
  22. }

还有另外两个打印对象信息的调试函数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中):

  1. #if !defined(Q_ASSERT)
  2. #  if defined(QT_CHECK_STATE)
  3. #  if defined(QT_FATAL_ASSERT)
  4. #  define Q_ASSERT(x)   //打印x,文件名,在程序源代码中的行号
  5. #   else
  6. #  define Q_ASSERT(x)
  7. #    endif
  8. #  else
  9. #    define Q_ASSERT(x)
  10. #  endif#endif

宏Q_CHECK_PTR实质上调用函数qWarning输出信息,宏定义Q_CHECK_PTR列出如下(在src/tools/qglobal.h中):

  1. #if defined(QT_CHECK_NULL)
  2. #  define Q_CHECK_PTR(p) (qt_check_pointer#else#  define Q_CHECK_PTR(p)
  3. #endif Q_EXPORT bool qt_check_pointer( bool c, const char *, int );

函数qt_check_pointer实现信息输出操作,函数列出如下(在src/tools/qglobal.cpp中):

  1. bool qt_check_pointer( bool c, const char *n, int l ){    if ( c ) qWarning( "In file %s, line %d: Out of memory", n, l );
  2. return TRUE;}

示例2:运行宏Q_ASSERT和Q_ASSERT

宏Q_ASSERT和Q_ASSERT常用来检测程序错误,下面例子使用了这两个宏:

  1. char *alloc( int size ){
  2. Q_ASSERT( size > 0 ); //如果size > 0表达式不成立,打印警告信息
  3. char *p = new char[size];
  4. Q_CHECK_PTR( p ); //如果指针p为空,打印警告信息
  5. return p;
  6. }

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: 打印不同类型的警告信息

下面的例子根据不同的宏定义打印不同类型的警告信息。代码如下:

  1. void f( char *p, int i ){
  2. #if defined(QT_CHECK_NULL) //检测危险的空指针
  3. if ( p == 0 )          qWarning( "f: Null pointer not allowed" );
  4. #endif #if defined(QT_CHECK_RANGE) //检测变量范围错误
  5. if ( i < 0 )
  6. qWarning( "f: The index cannot be negative" );
  7. #endif}

小结:QT核心编程之调试技术的内容介绍完了,需要本文能对你有所帮助,需要更多资料的话,请参考编辑推荐。

时间: 2024-08-03 22:08:32

QT核心编程之调试技术 (g)的相关文章

QT核心编程之Qt线程 (c)

QT核心编程之Qt线程是本节要介绍的内容,QT核心编程我们要分几个部分来介绍,想参考更多内容,请看末尾的编辑推荐进行详细阅读,先来看本篇内容. Qt对线程提供了支持,它引入了一些基本与平台无关的线程类.线程安全传递事件的方式和全局Qt库互斥量允许你从不同的线程调用Qt的方法.Qt中与线程应用相关的类如表6所示. 表6 Qt中与线程相关的类 使用线程需要Qt提供相应的线程库的支持,因此,在编译安装Qt时,需要加上线程支持选项. 当在Windows操作系统上编译Qt时,线程支持是在一些编译器上的一个

Qt on Android 核心编程

Qt on Android 核心编程(最好看的Qt编程书!CSDN博主foruok倾力奉献!) 安晓辉 著   ISBN 978-7-121-24457-5 2015年1月出版 定价:65.00元 444页 16开 编辑推荐 当Qt跨界牵手Android,移动开发会有什么不同?初学者如何借助Qt开发Android应用?跟随CSDN博文大赛冠军foruok进入Qt on Android无秘之旅! 内容提要 <Qt on Android 核心编程>以"从零开始也能学会Qton Andro

《Qt on Android核心编程》勘误

我的第一本技术书籍<Qt on Android核心编程>已经出版上市,书中难免疏漏,存在一些文字和技术上的问题,特记录在此. 本文会不停更新,拿到书的朋友发现问题可以回复本文,我回将问题更新到博文中.提前感谢各位啦. <Qt on Android核心编程>的试读样章在这里,点击下载.购买链接在下面: china-pub 亚马逊 京东1 京东2 淘宝惊喜价 编排说明 本文将结合章节和问题发现的先后顺序来编排,具体是酱紫的:每个章节单列出来作为本文的一节,在该节下按时间顺序列出发现的问

《Qt on Android核心编程》介绍

<Qt on Android核心编程>终于尘埃落定,付梓印刷了. 封面 看看封面的效果吧,历经几版,最终就成了这个样子. 看下封皮: 这是立体版效果: 章节内容简介 第 1 章 欢迎来到Qt的世界,让我们看看Qt是什么,能给我们带来什么,又有谁在使用Qt.我们要约会的Qt on Android,它缘起何处,有着怎样曲折婉转的历史,如今的小模样能否让我们爱之如狂-- 第 2 章 当你遇见了合适的人,开始筹划第一次约会,又是兴奋又是惆怅,要不要买花,去哪里买礼物,穿什么衣服,洒什么香水,带什么应对

Qt Quick核心编程从入门到精通

本文是个推荐文章,推荐foruok博主的Qt quick 核心编程的系列经典编程! foruok 博主 的Qt Quick系列文章: Qt Quick 简介 QML 语言基础 Qt Quick 之 Hello World 图文详解 Qt Quick 简单教程 Qt Quick 事件处理之信号与槽 Qt Quick事件处理之鼠标.键盘.定时器 Qt Quick 事件处理之捏拉缩放与旋转 Qt Quick 组件与对象动态创建详解 Qt Quick 布局介绍 Qt Quick 之 QML 与 C++

为什么写作《Qt Quick核心编程》

我的第二本书<Qt Quick 核心编程>上市了,各个网站的预售链接已经上线: 淘宝惊喜价 china-pub 京东 亚马逊 本书的前言: 今年(2014年)4月份,我开始写作<Qt on Android核心编程>,该书主要讲述Qt on Android的核心技术,比如信号与槽.元对象系统.Qt与Android的衔接.Android相关的开发主题等,对于界面开发,还是基于Qt传统的Widgets. 在写作的过程中,不断有技术同仁向我咨询Qt Quick的问题,有诸如对象如何声明.怎

《Qt on Android核心编程》目录

有朋友想看看<Qt on Android核心编程>的目录,So-- 目录 <Qt on Android核心编程>目录,截了10张图才弄好,都在下面了. 内容说明 本书内容基于第一个正式支持 Qt on Android 的 Qt SDK 版本,5.2.0 ,写作过程中 Qt 5.3.0 发布,我调整了部分内容,对有变化的部分作了对应介绍. 从目录可以看出,<Qt on Android核心编程>是从 Qt 的核心概念--元对象系统--讲起的,涵盖了信号与槽.事件.多线程.网

《Qt on Android核心编程》预售链接出来了

本人的新书<Qt on Android核心编程>已经由电子工业出版社博文视点出版,目前china-pub正在预售,欢迎关注. 想了解目录的,看这里:<Qt on Android核心编程>目录. 骚情简介在这里:<Qt on Android核心编程>介绍.

《Qt on Android核心编程》相关资源

有不少朋友反馈在搭建 Qt on Android 开发环境时遇到了问题,诸如 Android SDK 无法下载. jdk 找不到合适的版本.创建 AVD 出错等等.为此我把与<Qt on Android核心编程>一书配套的相关工具和SDK都打包上传到了百度云上,列在这里供大家下载. 需要说明的是,我的Android SDK和相关工具,都是32位的,也都不是最新的.不过,我在 Qt 5.2.0 ,Qt 5.3.0 , Qt 5.3.1 , Qt 5.4.0 都试过,是可用的. Android N