博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
4、QT分析之调试跟踪系统
阅读量:7237 次
发布时间:2019-06-29

本文共 4592 字,大约阅读时间需要 15 分钟。

原文地址:http://blog.163.com/net_worm/blog/static/127702419201002004518944/

 

在我们前面的分析中,经常看到qWarning()和qDebug()之类的调用。今天深入的分析QT的调试跟踪系统。

我们先看QDebug.h中的宏定义:

1 #if !defined(QT_NO_DEBUG_STREAM) 2 Q_CORE_EXPORT_INLINE QDebug qDebug() { return QDebug(QtDebugMsg); } 3  4 #else // QT_NO_DEBUG_STREAM 5 #undef qDebug 6 inline QNoDebug qDebug() { return QNoDebug(); } 7 #define qDebug QT_NO_QDEBUG_MACRO 8  9 #ifdef QT_NO_MEMBER_TEMPLATES10 template
11 inline QNoDebug operator<<(QNoDebug debug, const T &) { return debug; }12 #endif13 14 #endif15 16 #if !defined(QT_NO_WARNING_OUTPUT)17 Q_CORE_EXPORT_INLINE QDebug qWarning() { return QDebug(QtWarningMsg); }18 #else19 #undef qWarning20 inline QNoDebug qWarning() { return QNoDebug(); }21 #define qWarning QT_NO_QWARNING_MACRO22 #endif

这里很明显,QT的调试跟踪系统就是两条:DEBUG和WARNING。先看DEBUG,如果我们定义了宏QT_NO_DEBUG_STREAM,qDebug()被定义成QNoDebug(),而QT_NO_QDEBUG_MACRO的定义:

1 #define QT_NO_QDEBUG_MACRO if(1); else qDebug

注意if后面的分号,其等价于空语句。

我们再看QNoDebug类的定义:

1 class QNoDebug 2 { 3 public: 4     inline QNoDebug(){} 5     inline QNoDebug(const QDebug &){} 6     inline ~QNoDebug(){} 7 #if !defined( QT_NO_TEXTSTREAM ) 8     inline QNoDebug &operator<<(QTextStreamFunction) { return *this; } 9     inline QNoDebug &operator<<(QTextStreamManipulator) { return *this; }10 #endif11     inline QNoDebug &space() { return *this; }12     inline QNoDebug &nospace() { return *this; }13     inline QNoDebug &maybeSpace() { return *this; }14 15 #ifndef QT_NO_MEMBER_TEMPLATES16     template
17 inline QNoDebug &operator<<(const T &) { return *this; }18 #endif19 };

重载的<<操作只是返回其自身。另外一种情况(就是有DEBUG_STREAM)的时候,也就是缺省情况下,qDebug被定为QDebug,QDebug的输出设备是什么呢?看QDebug类中构造的定义:

1     inline QDebug(QIODevice *device) : stream(new Stream(device)) {}2     inline QDebug(QString *string) : stream(new Stream(string)) {}3     inline QDebug(QtMsgType t) : stream(new Stream(t)) {}4     inline QDebug(const QDebug &o):stream(o.stream) { ++stream->ref; }

可以知道QDebug的输出设备可以使QString,QIODevice或者QtMsgType指定的类型。

如果我们在main()函数里面写这样一行程序:

1 qDebug() << "Hello world!";

其执行的效果是向stderr设备输出"Hello world!",根据

1 Q_CORE_EXPORT_INLINE QDebug qDebug() { return QDebug(QtDebugMsg); }

定义,实际调用的是:

1 inline QDebug(QtMsgType t) : stream(new Stream(t)) {}

语句,在新生成Stream对象的时候,调用的是:

1 Stream(QtMsgType t) : ts(&buffer, QIODevice::WriteOnly), ref(1), type(t), space(true), message_output(true) {}

执行完毕之后,会释放QDebug对象,看看QDebug的释放:

 

1 inline ~QDebug() {2         if (!--stream->ref) {3             if(stream->message_output)4                 qt_message_output(stream->type, stream->buffer.toLocal8Bit().data());5             delete stream;6         }7     }

我们再来看qt_message_output()的代码:

 

1 void qt_message_output(QtMsgType msgType, const char *buf) 2 { 3     if (handler) { 4         (*handler)(msgType, buf); 5     } else { 6 #if defined(Q_CC_MWERKS) 7         mac_default_handler(buf); 8 #elif defined(Q_OS_WINCE) 9         QString fstr = QString::fromLatin1(buf);10         fstr += QLatin1String("\n");11         OutputDebugString(reinterpret_cast
(fstr.utf16()));12 #else13 fprintf(stderr, "%s\n", buf);14 fflush(stderr);15 #endif16 }17 18 if (msgType == QtFatalMsg19 || (msgType == QtWarningMsg20 && (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) {21 22 #if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)23 // get the current report mode24 int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);25 _CrtSetReportMode(_CRT_ERROR, reportMode);26 #if !defined(Q_OS_WINCE)27 int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, buf);28 #else29 int ret = _CrtDbgReportW(_CRT_ERROR, _CRT_WIDE(__FILE__),30 __LINE__, _CRT_WIDE(QT_VERSION_STR), reinterpret_cast
(QString::fromLatin1(buf).utf16()));31 #endif32 if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW)33 return; // ignore34 else if (ret == 1)35 _CrtDbgBreak();36 #endif37 38 #if (defined(Q_OS_UNIX) || defined(Q_CC_MINGW))39 abort(); // trap; generates core dump40 #else41 exit(1); // goodbye cruel world42 #endif43 }44 }

首先是判断用户有没有handler,如果有这个处理能力就让用户自己处理:

1 static QtMsgHandler handler = 0;                // pointer to debug handler

在Qglobal.cpp中定义。要是想自己处理,只要让handler指向自己的处理函数就可以了,多少有点C程序的味道。

否则的话就会输出到stderr设备上(Win系统中非WinCE的情况)。

其他,如果是FATAL(致命)错误或者警告,则会调用_CrtDbgReport(),其模式是_CRT_ERROR。也就是往调试器报告致命错误。QWarning的实现基本类似,不再深入一步一步分析。

 

转自:
http://www.cnblogs.com/lfsblack/p/5279170.html
你可能感兴趣的文章
css实现三栏布局的几种方法及优缺点
查看>>
proxychains是怎么工作的
查看>>
React16性能改善的原理一
查看>>
网页水印SDK的实现
查看>>
js的观察者模式
查看>>
函数柯里化
查看>>
手把手教你搭建智能合约测试环境、开发、编译、部署以及如何通过JS调用合约方法...
查看>>
Flex 布局教程
查看>>
固定宽度布局开发WebApp如何实现多终端下自适应?
查看>>
伟大的Scrum团队的特征
查看>>
2019春节防坑指南之抢票陷阱(文末有彩蛋)
查看>>
深入node.js-浏览器缓存机制
查看>>
解决IOS中input失焦后,页面上移,点击不了问题
查看>>
【C】 23_#error 和 #line 使用分析
查看>>
浅谈 Java 10 ,你可能不知道的五件事
查看>>
IT 人能在一线城市里生活一辈子吗?
查看>>
VUE的总结(1)
查看>>
【PWA学习与实践】(5)在Web中进行服务端消息推送
查看>>
WebAssembly完全入门——了解wasm的前世今身
查看>>
SAP CRM和C4C数据同步的两种方式概述:SAP PI和HCI
查看>>