0. 问题
在学习Qt 开发时,为了方便输出日志以查看问题, Google了优化方法,即:
QApplication a(argc, argv);
qInstallMessageHandler(myMessageOutput);
使用 qInstallMessageHandler函数添加自定义的日志处理, 基本网上搜到的代码如下:
void LogManager::CustomMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
switch (type) {
case QtDebugMsg:
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtInfoMsg:
fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtWarningMsg:
fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtCriticalMsg:
fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtFatalMsg:
fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
abort();
}
}
然后在 main.cpp中测试:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qInstallMessageHandler(LogManager::CustomMessageHandler);
qDebug("Debug Message");
qInfo("Info Message");
qWarning("Warning Message");
qCritical("Critical Message");
qFatal("Fata Message");
MainWindow w;
w.show();
return a.exec();
}
点击debug 运行,打开 应用程序输出, 然后你会惊奇的发现:
没有任何日志!!!
没有任何日志!!!
没有任何日志!!!
1. 分析
首先对比测试不设置 qInstallMessageHandler 是否能正常显示, 于是修改代码如下:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// qInstallMessageHandler(LogManager::CustomMessageHandler);
qDebug("Debug Message");
qInfo("Info Message");
qWarning("Warning Message");
qCritical("Critical Message");
// qFatal("Fata Message");
MainWindow w;
w.show();
return a.exec();
}
运行,查看"应用程序输出" :
上图说明能正常输出日志.那么问题就出在 qInstallMessageHandler的函数中。
2. 解决
经过Google搜索:
中文的结果几乎全是如何设置自定义日志输出的, 也有的说把 stderr
换成 stdout
, 根据建议修改,运行,然后不出意外的出意外了, 还是不显示!
随机改为英文搜索:
还是英文比较好一些, 第一个就是类似的问题,在 Qt的官方论坛中有人同样有此问题
qInstallMessageHandler not showing anything when in debug mode | Qt Forum
https://forum.qt.io/topic/136623/qinstallmessagehandler-not-showing-anything-when-in-debug-mode
最佳答案是:
Hi, I also use qInstallMessageHandler and I remember also having problems with debug output: inside Qt there is a check for recursive calls to a custom message handler (in case there's a qDebug() call inside your message handler for example) so I ended up calling the Win32 OutputDebugString() directly in my message handler, like this:
::OutputDebugStringA(qUtf8Printable(msg + "\n"));
In Linux and on the Mac fprintf() and fflush() work fine, it's just Windows that needs this workaround. Maybe it can solve your problem too...
翻译过来就是在Windows平台有bug, 使用fprintf + fflush不输出, 建议使用 ::OutputDebugStringA(qUtf8Printable(msg + "\n"));
, 于是改造函数为:
#ifdef WIN32
#include "windows.h"
#endif
#include "LogManager.h"
void LogManager::CustomMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray localMsg = msg.toUtf8();
#ifdef WIN32
QString outputMsg;
switch (type) {
case QtDebugMsg:
outputMsg = QString("Debug: %1 (%2:%3, %4)").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function);
break;
case QtInfoMsg:
outputMsg = QString("Info: %1 (%2:%3, %4)").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function);
break;
case QtWarningMsg:
outputMsg = QString("Warning: %1 (%2:%3, %4)").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function);
break;
case QtCriticalMsg:
outputMsg = QString("Critical: %1 (%2:%3, %4)").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function);
break;
case QtFatalMsg:
outputMsg = QString("Fatal: %1 (%2:%3, %4)").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function);
abort();
}
// 使用 OutputDebugStringA 输出消息
::OutputDebugStringA(qUtf8Printable(outputMsg + "\n"));
#else
switch (type) {
case QtDebugMsg:
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtInfoMsg:
fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtWarningMsg:
fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtCriticalMsg:
fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtFatalMsg:
fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
abort();
}
#endif
}
运行效果如下: