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

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

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

 #if !defined(QT_NO_DEBUG_STREAM)
Q_CORE_EXPORT_INLINE QDebug qDebug() { return QDebug(QtDebugMsg); } #else // QT_NO_DEBUG_STREAM
#undef qDebug
inline QNoDebug qDebug() { return QNoDebug(); }
#define qDebug QT_NO_QDEBUG_MACRO #ifdef QT_NO_MEMBER_TEMPLATES
template<typename T>
inline QNoDebug operator<<(QNoDebug debug, const T &) { return debug; }
#endif #endif #if !defined(QT_NO_WARNING_OUTPUT)
Q_CORE_EXPORT_INLINE QDebug qWarning() { return QDebug(QtWarningMsg); }
#else
#undef qWarning
inline QNoDebug qWarning() { return QNoDebug(); }
#define qWarning QT_NO_QWARNING_MACRO
#endif

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

 #define QT_NO_QDEBUG_MACRO if(1); else qDebug

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

我们再看QNoDebug类的定义:

 class QNoDebug
{
public:
inline QNoDebug(){}
inline QNoDebug(const QDebug &){}
inline ~QNoDebug(){}
#if !defined( QT_NO_TEXTSTREAM )
inline QNoDebug &operator<<(QTextStreamFunction) { return *this; }
inline QNoDebug &operator<<(QTextStreamManipulator) { return *this; }
#endif
inline QNoDebug &space() { return *this; }
inline QNoDebug &nospace() { return *this; }
inline QNoDebug &maybeSpace() { return *this; } #ifndef QT_NO_MEMBER_TEMPLATES
template<typename T>
inline QNoDebug &operator<<(const T &) { return *this; }
#endif
};

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

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

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

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

 qDebug() << "Hello world!";

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

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

定义,实际调用的是:

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

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

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

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

 inline ~QDebug() {
if (!--stream->ref) {
if(stream->message_output)
qt_message_output(stream->type, stream->buffer.toLocal8Bit().data());
delete stream;
}
}

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

 void qt_message_output(QtMsgType msgType, const char *buf)
{
if (handler) {
(*handler)(msgType, buf);
} else {
#if defined(Q_CC_MWERKS)
mac_default_handler(buf);
#elif defined(Q_OS_WINCE)
QString fstr = QString::fromLatin1(buf);
fstr += QLatin1String("\n");
OutputDebugString(reinterpret_cast<const wchar_t *> (fstr.utf16()));
#else
fprintf(stderr, "%s\n", buf);
fflush(stderr);
#endif
} if (msgType == QtFatalMsg
|| (msgType == QtWarningMsg
&& (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) { #if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
// get the current report mode
int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
_CrtSetReportMode(_CRT_ERROR, reportMode);
#if !defined(Q_OS_WINCE)
int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, buf);
#else
int ret = _CrtDbgReportW(_CRT_ERROR, _CRT_WIDE(__FILE__),
__LINE__, _CRT_WIDE(QT_VERSION_STR), reinterpret_cast<const wchar_t *> (QString::fromLatin1(buf).utf16()));
#endif
if (ret == && reportMode & _CRTDBG_MODE_WNDW)
return; // ignore
else if (ret == )
_CrtDbgBreak();
#endif #if (defined(Q_OS_UNIX) || defined(Q_CC_MINGW))
abort(); // trap; generates core dump
#else
exit(); // goodbye cruel world
#endif
}
}

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

 static QtMsgHandler handler = ;                // pointer to debug handler

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

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

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

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

  1. 4、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. 4-c++教程起航篇-学习笔记

    c++教程起航篇 我们会讲C++那些事,C++与C语言的关系. C++诞生于贝尔实验室. C++之父: 本贾尼·斯特劳斯特卢普 C++社区排行榜 最新排行,c++排名第三,Python排名第四 C++ ...

  2. JavaWeb——升级赛-学生成绩管理系统(1)jsp---19.01.03

    add.jsp <%@ page language="java" contentType="text/html; charset=UTF-8"    pa ...

  3. 20145202马超《网络对抗》Exp5MSF基础应用

    20145202马超<网络对抗>Exp5MSF基础应用 本实践目标,掌握metasploit的基本应用方式,掌握常用的三种攻击方式的思路.具体需要完成(1)一个主动攻击,如ms08_067 ...

  4. P1488 肥猫的游戏

    题目描述 野猫与胖子,合起来简称肥猫,是一个班的同学,他们也都是数学高手,所以经常在一起讨论数学问题也就不足为奇了.一次,野猫遇到了一道有趣的几何游戏题目,便拿给胖子看.游戏要求在一个有n个顶点凸多边 ...

  5. 成都Uber优步司机奖励政策(1月25日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  6. agc 027 B - Garbage Collector

    B - Garbage Collector https://agc027.contest.atcoder.jp/tasks/agc027_b 题意: x坐标轴上n个垃圾,有一个机器人在从原点,要清扫垃 ...

  7. dvs-panotracking编译运行

    编译运行dvs-panotracking > 编译dvs-panotracking之前首先需要安装imageutilities . 源码下载 https://github.com/VLOGrou ...

  8. DE1-SOC工程helloworld-第一篇(未完成)

    1. 参考官方的文档,第一个问题就是电脑上需要安装ubuntu虚拟机吗? 2. 创建一个“Hello world”工程:在Linux terminal 上打印信息. 3. 说是让安装个EDS软件,先去 ...

  9. Omad群组部署、依赖部署一键解决

    本文来自网易云社区 作者:李培斌 前言 基于omad部署平台实现一键部署的实践已有很多成功的经验,杭研QA的技术先锋们也在ks圈里有很多不同的文章去阐述关于这类需求的实现和思路,当然包括我们金融事业部 ...

  10. spark history server

    参考:http://blog.csdn.net/lsshlsw/article/details/44786575 为什么需要historyServer? 在运行Spark Application的时候 ...