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的幫助文檔。下面說明如何打印各類調試或警告信息app

一、命令行參數函數

當你運行Q應用程序時,你能夠指定幾個命令行參數來幫助你調試。這幾個命令行參數說明以下:工具

-nograb 應用程序再也不捕獲鼠標或者鍵盤。當程序在Linux下運行在gdb調試器中時這個選項是默認的。測試

-dograb 忽略任何隱含的或明顯得-nograb。即便-nograb出如今命令行的最後,-dograb也會超過-nograb生效的。優化

-sync 在X同步模式下運行應用程序。同步模式強迫X服務器當即執行每個X客戶端的請求,而不使用緩存優化。它使得程序更加容易測試而且一般會更慢。-sync模式只對X11版本的Qt有效。spa

二、打印警告和調試消息操作系統

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.    }  

在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;  

示例:應用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();  

還有另外兩個打印對象信息的調試函數QObject::dumpObjectTree()和QObject::dumpObjectInfo()。它們只在程序調試版本下,輸出信息,在發佈版本中,這兩個函數不起做用。函數QObject::dumpObjectInfo()打印一個對象信號鏈接等方面的信息。函數QObject::dumpObjectTree()打印出子對象樹。

三、調試宏

在程序運行中還常使用宏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  
  11.  

宏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;  

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核心編程之調試技術的內容介紹完了,須要本文能對你有所幫助,須要更多資料的話,請參考編輯推薦。

相關文章
相關標籤/搜索