一、qInstallMessageHandler
QtMessageHandler qInstallMessageHandler(QtMessageHandler handler)
qInstallMessageHandler
是 Qt 框架中用于自定义消息处理的核心函数,主要用于拦截和重定向 Qt 应用程序的日志输出(如 qDebug()
、qWarning()
等)。
作用机制:
替换 Qt 默认的消息处理器,允许开发者自定义日志输出方式(如写入文件、发送到网络等)。传入的 handler
需匹配 void(QtMsgType, const QMessageLogContext&, const QString&)
函数签名。
参数说明:
1.handler: 自定义处理函数指针,若传入 nullptr 则恢复默认处理器。
2.返回值:指向前一个处理器的指针,便于链式调用或恢复。
二、QtMessageHandler handler
void(QtMsgType, const QMessageLogContext&, const QString&)
这是一个Qt框架中用于自定义消息处理的函数签名类型,主要用于qInstallMessageHandler
注册自定义日志处理器。
参数说明:
1.QtMsgType
Qt定义的枚举类型,标识消息级别,包括:
QtDebugMsg:调试信息(qDebug触发)
QtInfoMsg:普通信息(qInfo触发)
QtWarningMsg:警告信息(qWarning触发)
QtCriticalMsg:严重错误(qCritical触发)
QtFatalMsg:致命错误(qFatal触发)
2. QMessageLogContext
包含日志上下文信息的结构体,成员包括:
file:源代码文件名
line:代码行号
function:函数名
category:日志分类(Qt5.5+支持)
3. QString&
实际日志内容的引用,需注意线程安全处理。
三、利用glog捕捉崩溃日志
google::InstallFailureWriter(&SignalHandler);
google::InstallFailureWriter(&SignalHandler)
是 Google Glog 日志库提供的核心函数,用于注册程序崩溃时的自定义信号处理器。
功能说明
当程序触发致命错误(如 SIGSEGV
、SIGABRT
)时,自动调用绑定的 SignalHandler
函数,将崩溃信息写入日志文件或控制台。
参数要求
SignalHandler 函数签名
需匹配 void(const char* data, size_t size)
格式:
data:崩溃信息的字符指针
size:信息长度
四、代码示例
log_test.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
QMAKE_LFLAGS += -no-pie
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
INCLUDEPATH += /usr/include/glog
LIBS += /usr/lib/x86_64-linux-gnu/libglog.so
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_debug_clicked();
void on_pushButton_warn_clicked();
void on_pushButton_crash_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_debug_clicked()
{
qDebug()<<"这是一条调试信息日志。";
}
void MainWindow::on_pushButton_warn_clicked()
{
qWarning()<<"这是一条警告信息日志。";
}
void MainWindow::on_pushButton_crash_clicked()
{
QVector<int> vec;
qDebug()<<"第一个数据为:"<<vec.at(0);
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QDateTime>
#include <QDir>
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <QMutex>
#include <fstream>
#include "logging.h"
#include "log_severity.h"
QtMessageHandler gDefaultHandler = nullptr;
static QMutex logMutex;
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
QMutexLocker locker(&logMutex);
QDateTime time = QDateTime::currentDateTime();
QString strTime = time.toString("MM-dd hh:mm:ss");
QString strMessage = QString("[%1] [%2:%3] %4").arg(strTime).arg(QString(context.file).split("/").last()).arg(context.line).arg(msg);
QString content;
switch(type)
{
//调试信息提示
case QtDebugMsg:
content = QString("[调试信息] %1").arg(strMessage);
break;
//一般的warning提示
case QtWarningMsg:
content = QString("[警告信息] %1").arg(strMessage);
break;
//严重错误提示
case QtCriticalMsg:
content = QString("[严重错误] %1").arg(strMessage);
break;
//致命错误提示
case QtFatalMsg:
content = QString("[致命错误] %1").arg(strMessage);
abort();
default:
break;
}
QString strPath = QCoreApplication::applicationDirPath() + "/log/";
QFile runLog(strPath + "log.txt");
runLog.open(QIODevice::WriteOnly | QIODevice::Append);
if(runLog.size() >= 1024 * 5000)
{
runLog.close();
QString backupName = QString("log_%1.txt").arg(QDateTime::currentDateTime().toString("yyyy_MM_dd_hh_mm_ss"));
QFile::copy(strPath + "log.txt", strPath + backupName);
runLog.remove();
QFile outFile3(strPath + "log.txt");
outFile3.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream ts(&outFile3);
ts << content << endl;
}
else
{
QTextStream ts(&runLog);
ts << content << endl;
}
//
if(gDefaultHandler)
{
gDefaultHandler(type, context, msg);
}
}
// 扑捉到程序崩溃或者中断时,把相应的信息打印到log文件和输出到屏幕。
void SignalHandler(const char* data, int size) {
QString logPath = QCoreApplication::applicationDirPath() + "/log/crash/" ;
//组织文件名称
QString strTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
logPath = logPath + strTime + ".log";
std::string glog_file = logPath.toStdString();
//创建文件
std::ofstream fs(glog_file, std::ios::app);
//打印到文件
std::string str = std::string(data, size);
if (fs.is_open()) {
fs.write(data, size);
}
fs.close();
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QString path = QCoreApplication::applicationDirPath() + "/log";
QString logPath = path + "/crash";
QDir dir(logPath);
if(!dir.exists())
if(dir.mkpath(logPath))
qDebug()<<"创建路径:"<<logPath;
gDefaultHandler = qInstallMessageHandler(messageHandler);
google::InitGoogleLogging(argv[0]);//使用glog之前必须先初始化库,仅需执行一次,括号内为程序名
google::InstallFailureSignalHandler();
google::InstallFailureWriter(&SignalHandler);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.ui
运行结果
日志生成