Qt调试使用QDebug输出行等更详细的信息

真的是代码一增多,就容易产生各种逻辑错误,bug等。一个高效的调试输出信息可以更快定位地定位问题。 在网上搜了下Qt的调试,qDebug() 输出,真的是没有什么有用的啊,还是自己研究分享个吧!

qDebug() 的遗憾

Qt提供了很方便的输出调试信息的宏 qDebug , qInfo, qWarning, qCritical, qFatal 。这些宏通过QMessageLogger类来管理,自动创建一个QDebug临时对象来输出调试信息到Qt的日志管理器。遗憾的是,这个宏只输出传入的信息,无法通过设置来输出行,函数,文件等信息,至少根据我目前的认识和网上的信息是没找到办法的。

如何优雅地输出更多的调试信息

  • 通过万能的宏
    1. 有人引入了C++标准里的cout。不知道意义何在。既要包含 ,引入std命名空间,而且风格很怪异,更重要的是,cout默认是向标准输出流中写数据,Qt的日志管理器可收不到。
    2. 有人使用qDebug(const char *message, …)。类似如下:
    #define myDebug(format, ...) qDebug("[Debug] "format" File:%s, Line:%d, Function:%s", __VA_ARGS__, __FILE__, __LINE__ , __FUNCTION__); 有改进,可是如果用这种形式的话,QDebug重载的“ operator << ” 的强大之处就全都没法用了,这样当直接输出一些对象时会很难受。
    3. 还有组合两个qDebug()来输出的形式。类似如下:#define myDebug qDebug("[Debug] File:%s, Line:%d, Function:%s, __FINE__, __LINE__ , __FUNCTION__"); qDebug() 可是这种输出时肯定是分割的两行。

  • 使用消息处理
    消息处理是一个函数,用于打印调试信息、警告信息、严重错误和致命的错误的消息。使用qInstallMessageHandler()这个全局函数就可以把qDebug()等信息传给先前定义的消息处理函数。消息处理函数就类似一个回调函数,格式如下 void myMessageHandler(QtMsgType, const QMessageLogContext &, const QString &);
    Qt帮助文档里给了个例子:

    static void myMessageOutput(QtMsgType type, const QMessageLogContext     &context, const QString &msg)
    {
       QByteArray localMsg = msg.toLocal8Bit();
       const char *file = context.file ? context.file : "";
       const char *function = context.function ? context.function : "";
       switch (type) {
       case QtDebugMsg:
           fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
           break;
       case QtInfoMsg:
           fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
           break;
       case QtWarningMsg:
           fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
           break;
       case QtCriticalMsg:
           fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
           break;
       case QtFatalMsg:
           fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
           break;
       }
    }
    

    这种方法,不仅可以输出调试信息,而且可以很直观、很方便的得到输出代码所在的文件、函数、行号等信息。而且还可以更加方便的丰富其功能。显然很适合正式项目,大型工程使用。
    重大缺点:测试时,在使用这个函数输出的日志信息,好像存在缓冲,也就是不能及时地输出,而是在达到一定量的时候就一次性输出了。这难道就是官方文档中说的达到抑制运行时日志输出。 但是,网上搜到的qInstallMessageHandler相关的信息都没有提及这个问题,不知是否是我个人版本问题。

一个输出行等详细信息的宏

最后还是自己用QDebug类设计了个简单的日志输出的宏。设计了两种使用风格。没有牺牲“<<” 运算符,去掉了qDebug的括号,函数信息也更完整。可自行根据个人风格修改。
效果:

xdebug << screen->geometry() << QString("大小 %1").arg(56) << 789;
zdebug(screen->geometry() << QString("大小 %1").arg(56) << 789);

Debug: [26 @Widget::Widget(QWidget*) @..\UDP\widget.cpp] MSG: QRect(0,0 1366x768) "大小 56" 789
Debug:  QRect(0,0 1366x768) "大小 56" 789 [Widget::Widget(QWidget*) @..\UDP\widget.cpp(27)]

代码:

#define xdebug   (QDebug(QtDebugMsg).nospace() << \
        "Debug: [" << __LINE__ << " @"  << Q_FUNC_INFO  << " @" << __FILE__ << "] MSG:").space()
#define zdebug(...)   (QDebug(QtDebugMsg) \
        << "Debug: " << __VA_ARGS__ ).nospace() << '[' << Q_FUNC_INFO << " @" << __FILE__ << '(' << __LINE__ << ")]";

#define xinfo   (QDebug(QtInfoMsg).nospace() << \
        "Info: [" << __LINE__ << " @"  << Q_FUNC_INFO  << " @" << __FILE__ << "] MSG:").space()
#define zinfo(...)   (QDebug(QtInfoMsg) \
        << "Info: " << __VA_ARGS__ ).nospace() << '[' << Q_FUNC_INFO << " @" << __FILE__ << '(' << __LINE__ << ")]";

#define xwarning   (QDebug(QtWarningMsg).nospace() << \
        "Warning: [" << __LINE__ << " @"  << Q_FUNC_INFO  << " @" << __FILE__ << "] MSG:").space()
#define zwarning(...)   (QDebug(QtWarningMsg) \
        << "Warning: " << __VA_ARGS__ ).nospace() << '[' << Q_FUNC_INFO << " @" << __FILE__ << '(' << __LINE__ << ")]";

#define xcritical   (QDebug(QtCriticalMsg).nospace() << \
        "Critical: [" << __LINE__ << " @"  << Q_FUNC_INFO  << " @" << __FILE__ << "] MSG:").space()
#define zcritical(...)   (QDebug(QtCriticalMsg) \
        << "Critical: " << __VA_ARGS__ ).nospace() << '[' << Q_FUNC_INFO << " @" << __FILE__ << '(' << __LINE__ << ")]";
//注意使用fatal会使程序终止
#define xfatal   (QDebug(QtFatalMsg).nospace() << \
        "Fatal: [" << __LINE__ << " @"  << Q_FUNC_INFO  << " @" << __FILE__ << "] MSG:").space()
#define zfatal(...)   (QDebug(QtFatalMsg) \
        << "Fatal: " << __VA_ARGS__ ).nospace() << '[' << Q_FUNC_INFO << " @" << __FILE__ << '(' << __LINE__ << ")]";

希望对你有所帮助,也希望有同志看到后,赐教下qInstallMessageHandler的那个延迟问题。

今天天气不一般的热!


Qt调试使用QDebug输出行等更详细的信息_第1张图片

你可能感兴趣的:(代码技术等)