原文地址: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的实现基本类似,不再深入一步一步分析。

最新文章

  1. IOS_反射
  2. Android中dp,px,sp概念梳理以及如何做到屏幕适配
  3. Android 常见Crash Log汇总
  4. 免费api大全(更新中)
  5. Hibernate JPA 中配置Ehcache二级缓存
  6. Java多线程异常处理
  7. QM3_Statistics Concepts and Market Returns
  8. 产品经理之UML表达业务逻辑
  9. Java oop(一些自己的理解,并没有展开很细)
  10. BFC 原理
  11. 用Python计算幂的两种方法,非递归和递归法
  12. hashMap源码解析(五)
  13. Python 数字(Number)
  14. iframe之父子页面通信
  15. 关于.net程序集引用不匹配的问题
  16. 【代码审计】QYKCMS_v4.3.2 任意文件删除漏洞分析
  17. Mybatis Blob和String互转,实现文件上传等。
  18. 校园网突围之路由器开wifi__windows版
  19. hdu 3123 GCC (2009 Asia Wuhan Regional Contest Online)
  20. DesUtils工具类

热门文章

  1. HyperLedger Fabric 1.4 Solo模式简介(10.1)
  2. golang 多维哈希(map,hashmap)实践随笔
  3. linux (ubuntu)安装pycharm
  4. 通过c#操作word文档的其他方式
  5. 北京Uber优步司机奖励政策(2月25日)
  6. cyclone4驱动LM75A温湿度传感器学习
  7. Python Map 并行
  8. javaweb(五)——Servlet开发(一)
  9. selenium自动化之显式等待和EC(expected_conditions)模块
  10. CentOS安装nmon