原文地址: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_TEMPLATES
10 template<typename T>
11 inline QNoDebug operator<<(QNoDebug debug, const T &) { return debug; }
12 #endif
13
14 #endif
15
16 #if !defined(QT_NO_WARNING_OUTPUT)
17 Q_CORE_EXPORT_INLINE QDebug qWarning() { return QDebug(QtWarningMsg); }
18 #else
19 #undef qWarning
20 inline QNoDebug qWarning() { return QNoDebug(); }
21 #define qWarning QT_NO_QWARNING_MACRO
22 #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 #endif
11 inline QNoDebug &space() { return *this; }
12 inline QNoDebug &nospace() { return *this; }
13 inline QNoDebug &maybeSpace() { return *this; }
14
15 #ifndef QT_NO_MEMBER_TEMPLATES
16 template<typename T>
17 inline QNoDebug &operator<<(const T &) { return *this; }
18 #endif
19 };

重载的<<操作只是返回其自身。另外一种情况(就是有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<const wchar_t *> (fstr.utf16()));
12 #else
13 fprintf(stderr, "%s\n", buf);
14 fflush(stderr);
15 #endif
16 }
17
18 if (msgType == QtFatalMsg
19 || (msgType == QtWarningMsg
20 && (!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 mode
24 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 #else
29 int ret = _CrtDbgReportW(_CRT_ERROR, _CRT_WIDE(__FILE__),
30 __LINE__, _CRT_WIDE(QT_VERSION_STR), reinterpret_cast<const wchar_t *> (QString::fromLatin1(buf).utf16()));
31 #endif
32 if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW)
33 return; // ignore
34 else if (ret == 1)
35 _CrtDbgBreak();
36 #endif
37
38 #if (defined(Q_OS_UNIX) || defined(Q_CC_MINGW))
39 abort(); // trap; generates core dump
40 #else
41 exit(1); // goodbye cruel world
42 #endif
43 }
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

4、QT分析之调试跟踪系统的更多相关文章

  1. QT分析之调试跟踪系统

    原文地址:http://blog.163.com/net_worm/blog/static/127702419201002004518944/ 在我们前面的分析中,经常看到qWarning()和qDe ...

  2. Dapper,大规模分布式系统的跟踪系统--转

    原文地址:http://bigbully.github.io/Dapper-translation/ 概述 当代的互联网的服务,通常都是用复杂的.大规模分布式集群来实现的.互联网应用构建在不同的软件模 ...

  3. Dapper,大规模分布式系统的跟踪系统

    概述 当代的互联网的服务,通常都是用复杂的.大规模分布式集群来实现的.互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发.可能使用不同的编程语言来实现.有可能布在了几千台服务器 ...

  4. logback MDC(Mapped Diagnostic Context)与分布式系统的跟踪系统

    logback MDC(Mapped Diagnostic Context)与分布式系统的跟踪系统 logback官方文档中第8章Mapped Diagnostic Context给我们提供了一些分布 ...

  5. 【转】使用JIRA搭建企业问题跟踪系统【个人推荐】

    免责声明:     本文转自网络文章,转载此文章仅为个人收藏,分享知识,如有侵权,请联系博主进行删除.     原文作者:Judy Shen的专栏     原文地址:使用JIRA搭建企业问题跟踪系统 ...

  6. 理解WebKit和Chromium: 调试Android系统上的Chromium

    转载请注明原文地址:http://blog.csdn.net/milado_nju 1. Android上的调试技术 在Android系统上,开发人员能够使用两种不同的语言来开发应用程序,一种是Jav ...

  7. TaintDroid:智能手机监控实时隐私信息流跟踪系统(一)

    1.1     摘要 现今,智能手机操作系统不能有效的提供给用户足够的控制权并且很清楚的了解到第三方的应用程序是如何使用其的隐私数据.我们使用了TaintDroid来阐明这个缺点,其是一个高效的,全系 ...

  8. 微服务之分布式跟踪系统(springboot+zipkin+mysql)

    通过上一节<微服务之分布式跟踪系统(springboot+zipkin)>我们简单熟悉了zipkin的使用,但是收集的数据都保存在内存中重启后数据丢失,不过zipkin的Storage除了 ...

  9. 10、QT分析之WebKit

    该文章整理自 网易博客 http://blog.163.com/net_worm/blog/static/12770241920101831312381/ 转载请注明出处 WebKit是QT4新整合的 ...

随机推荐

  1. 【Unity】4.6 灯光

    分类:Unity.C#.VS2015 创建日期:2016-04-11 一.简介 灯光(Light,也叫光源)是每一个场景的重要组成部分,用于照亮场景和对象,从而让游戏具有自己的个性和风格,比如利用灯光 ...

  2. 深入理解Linux内核-回收页框

    Linux 系统在为用户态进程和内核分配动态内存的时候,所作的检查是马马虎虎的对内核使用的许多磁盘高速缓存和内存高速缓存大小也同样不作限制. 页框回收算法(PFRA):1.在所有内存使用完之前,就必须 ...

  3. iOS9中怎样注冊远程通知

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 假设认为写的不好请多提意见,假设认为不错请多多支持点赞.谢谢! hopy ;) 在以往的版本号中,我们能够通过: [[UIApplicatio ...

  4. 菜鸟学Java(六)——简单验证码生成(Java版)

    验证码大家都知道,它的作用也不用我多说了吧.如果不太清楚请参见百度百科中的解释,一般验证码的生成就是随机产生字符(数字.字母或者汉字等),然后将这些生成的字符绘制成一张图片,再在图片上加上一些干扰元素 ...

  5. 数据库的ACID

    一.事务 定义:所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位. 准备工作:为了说明事务的ACID原理,我们使用银行账户及资金管理的案例进行分析. [sql] ...

  6. [翻译] Dremel made simple with Parquet

    首先自己的 blog 好久没有写技术相关的东西了,今天又动笔了,好高兴!然后转载请注明出处.最后开始正题: 原文:Dremel made simple with Parquet | Twitter E ...

  7. UNIX环境高级编程 apue.h头文件的配置

    http://jimslinbing.blog.163.com/blog/static/85054319201292712414518/ 1.到http://www.apuebook.com下载源码2 ...

  8. opencv项目报错_pFirstBlock==pHead解决办法

    备注: 我上次遇到这个问题的原因是项目设置为MTd导致的 OpenCV是MTd的,我要是改成MDd就编译报错,所以不能采用把项目改为MDd的办法,只能把OpenCV重新编译为MDd的,下载CMAKE, ...

  9. Lintcode: First Bad Version 解题报告

    First Bad Version http://lintcode.com/en/problem/first-bad-version The code base version is an integ ...

  10. 【Java】PreparedStatement VS Statement

    创建时: Statement statement = conn.createStatement();    PreparedStatement preStatement = conn.prepareS ...