zoukankan      html  css  js  c++  java
  • 4、QT分析之调试跟踪系统

    原文地址: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("
    ");
    11         OutputDebugString(reinterpret_cast<const wchar_t *> (fstr.utf16()));
    12 #else
    13         fprintf(stderr, "%s
    ", 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
  • 相关阅读:
    Android 主题theme说明 摘记
    Android开发 去掉标题栏方法 摘记
    安卓项目五子棋代码详解(二)
    关于 ake sure class name exists, is public, and has an empty constructor that is public
    百度地图3.0实现图文并茂的覆盖物
    android onSaveInstanceState()及其配对方法。
    关于集成科大讯飞语音识别的 一个问题总结
    android 关于 webview 控制其它view的显示 以及更改view数据失败的问题总结
    C# 解析 json Newtonsoft果然强大,代码写的真好
    c#数据类型 与sql的对应关系 以及 取值范围
  • 原文地址:https://www.cnblogs.com/liushui-sky/p/6474021.html
Copyright © 2011-2022 走看看