真的是代码一增多,就容易产生各种逻辑错误,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的那个延迟问题。
今天天气不一般的热!