Qt 调试神器 QDebug

Qt 调试神器 QDebug

在 Qt 开发过程中,调试是不可或缺的环节,而 QDebug 作为 Qt 框架自带的调试输出工具,凭借其简洁易用、功能强大的特点,成为了开发者排查问题的得力助手。无论是基础的变量输出,还是复杂的自定义数据类型打印,QDebug 都能轻松应对。本文将从基础用法到进阶技巧,全面介绍 QDebug 的使用方法。

01 QDebug 基础用法:快速上手输出信息

QDebug 的基础用法非常简单,只需包含相关头文件并调用相应的输出函数,就能快速输出调试信息。

首先,在代码中需要包含 头文件,这是使用 QDebug 的前提。然后,最常用的就是 qDebug() 函数,它可以像 cout 一样直接输出各种基本数据类型,例如整数、浮点数、字符串等。

#include

...

int main() {

...

int num = 10;

float score = 95.5;

QString name = "Qt Developer";

qDebug() << "Number:" << num;

qDebug() << "Score:" << score;

qDebug() << "Name:" << name;

...

}

运行上述代码,在控制台中会清晰地输出相应的信息:

Number: 10

Score: 95.5

Name: "Qt Developer"

此外,qDebug() 还支持格式化输出,通过使用占位符来指定输出的格式。常用的占位符有 %d(整数)、%f(浮点数)、%s(字符串)等。

qDebug("Number: %d, Score: %.2f", num, score);

用法和printf相同,输出如下:

Number: 10, Score: 95.50

02 qDebug 输出自定义结构体

在实际开发中,我们经常需要输出自定义结构体的数据,以便查看结构体内部成员的取值。QDebug 支持通过重载 operator<< 运算符来实现自定义结构体的输出。

假设我们有一个 Person 结构体:

struct Person {

QString name;

int age;

QString address;

};

要让 QDebug 能够输出 Person 结构体,只需在结构体外部重载 operator<< 运算符:

QDebug operator<<(QDebug debug, const Person& person)

{

debug << "Person(name:" << person.name << ", age:" << person.age

<< ", address:" << person.address << ")"; return debug;

}

之后,就可以像输出基本数据类型一样输出 Person 结构体变量了:

Person person = {"Tom", 25, "Beijing"};

qDebug() << "Person Info:" << person;

输出结果如下:

Person Info: Person(name: "Tom" , age: 25 , address: "Beijing" )

03 配置日志格式

默认情况下,QDebug 的输出格式比较简单。但在实际开发中,我们可能需要在日志中包含时间、日志级别等信息,以便更好地追踪和分析问题。Qt 提供了相关的方法来配置终端日志格式。

我们可以通过 qSetMessagePattern() 函数来设置日志的输出格式,该函数接受一个字符串作为参数,字符串中可以包含各种占位符来指定日志的组成部分。

常用的占位符有:

%{appname}%{category}日志类别%{file}源文件路径%{function}函数%{line}

源文件中的行%{message}

实际消息%{pid}

PID%{threadid}

当前线程的全局 ID(如果可以获取)%{type}

"debug", "warning", "critical" or "fatal"%{time process}

消息发送时间,以进程启动以来的秒数为单位("process"是字面量)%{time boot}

消息发送时间,以系统启动以来的秒数为单位,如果可以确定("boot"是字面量)。如果无法获取自启动以来的时间,输出结果不确定(参见 QElapsedTimer::msecsSinceReference%{time [format]}

消息发生时的系统时间,通过将 format 传递给 QDateTime::toString ()进行格式化。如果未指定格式,则使用 Qt::ISODate 的格式。

消息发生时的系统时间,通过将 format 传递给 QDateTime::toString ()进行格式化。如果未指定格式,则使用 Qt::ISODate 的格式。

#include

#include

int main(int argc, char *argv[]) { QCoreApplication a(argc, argv);

qSetMessagePattern("{%time} {%type} {%function}:{%line} - {%message}");

qDebug() << "This is a debug message";

qWarning() << "This is a warning message"; qCritical() << "This is a critical message";

return a.exec();

}

输出结果如下:

[10:23:45.678] [debug] main.cpp:10 - This is a debug message[10:23:45.679] [warning] main.cpp:11 - This is a warning message[10:23:45.680] [critical] main.cpp:12 - This is a critical message

04 日志输出重定向

默认情况下,QDebug 的输出会显示在控制台中。但在某些场景下,我们可能需要将日志输出到文件、网络或其他地方,这就需要用到输出重定向功能。Qt 提供了 qInstallMessageHandler() 函数来实现自定义消息处理,从而实现输出重定向。

(一)重定向到文件

将日志输出到文件可以方便地保存日志信息,便于后续分析。以下是将日志重定向到文件的示例代码:

#include

#include

#include

#include

void fileMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) {

static QFile file("log.txt");

if (!file.isOpen()) {

file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text); }

QTextStream out(&file);

QString level;

switch (type) {

case QtDebugMsg: level = "Debug"; break; case QtWarningMsg: level = "Warning"; break; case QtCriticalMsg: level = "Critical"; break; case QtFatalMsg: level = "Fatal"; break;

default: level = "Unknown";

}

out << "[" << QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz") << "] [" << level << "] " << context.file << ":" << context.line << " - " << msg << endl;

file.flush();

}

int main(int argc, char *argv[]) {

QCoreApplication a(argc, argv);

qInstallMessageHandler(fileMessageHandler);

qDebug() << "This message will be written to log.txt"; qWarning() << "This warning will also be written to log.txt";

return a.exec();

}

运行上述代码后,日志信息会被写入到当前目录下的 log.txt 文件中。

(二)重定向到其他设备

除了文件,我们还可以将日志重定向到其他设备,例如网络套接字。只需在自定义的消息处理函数中,将日志信息发送到网络即可。具体实现需要结合网络编程相关知识,这里不再详细展开。

(三)重定向到三方日志库

在大型项目中,我们可能需要更强大的日志管理能力,如日志轮转、多线程安全、远程日志收集等。此时,将 QDebug 输出重定向到三方日志库是一个不错的选择。以下是几个常用的三方日志库推荐:

spdlog

log4cpp

Poco logging

05 日志分类输出

自从Qt5.2开始就加入了日志分类功能,陆陆续续再后续版本也添加了其他特性。要为输出的日志进行分类,需要提供类型参数,所以引入了新的日志宏:qCDebug()、qCInfo()、qCWarning() 和 qCCritical()。这些宏在头文件 QLoggingCategory 中声明。

入门的用法:

QLoggingCategory category("driver.usb");

qCDebug(category) << "a debug message";

#printf用法的格式化qCDebug(category, "a debug message logged into category %s", category.categoryName());

注意类型名称"dirver.usb"的定义存在限制,仅字母数字和点。

看下构造函数:

QLoggingCategory(constchar *category, QtMsgType enableForLevel = QtDebugMsg)

需要提供一个分类的字符串名称和输出限制级别。默认值所有级别的日志都会输出。如果指定了 Warning,那么比这个级别低的日志将不会输出。比如 Debug类型的就不会输出。

另外提供了两个宏方便声明 QLoggingCategory 静态变量。

// in a header

Q_DECLARE_LOGGING_CATEGORY(driverUsb)

// in one source file

Q_LOGGING_CATEGORY(driverUsb, "driver.usb")

宏定义如下,相当于头文件里声明了一个全局函数,源文件实现这个函数,返回一个静态的 QLoggingCategory 类型变量。

#define Q_DECLARE_LOGGING_CATEGORY(name) \externconst QLoggingCategory &name();#define Q_LOGGING_CATEGORY(name, ...) \const QLoggingCategory &name() \ { \staticconst QLoggingCategory category(__VA_ARGS__); \return category; \ }

同时日志分类之后,可以全局配置,限制指定模块日志是否输出。比如:

QLoggingCategory::setFilterRules("*.debug=false\n""driver.usb.debug=true");

日志的输出规则提供多种方式配置,优先级如下:

[QLibraryInfo::DataPath]/qtlogging.ini

QtProject/qtlogging.ini

setFilterRules()

QT_LOGGING_CONF(环境变量,指定配置文件的位置)

QT_LOGGING_RULES(环境变量,多条规则分号隔开)

日志格式化的时候也可以配置日志分类:

qSetMessagePattern("%{category} %{message}");

相关推荐

旺宝阿里巴巴收藏软件
365bet注册送

旺宝阿里巴巴收藏软件

📅 08-15 👁️ 9032
诗雅轩家具品牌涉及行业
365bet注册送

诗雅轩家具品牌涉及行业

📅 08-08 👁️ 198
《非人学园》银角免费获取攻略
365bet注册送

《非人学园》银角免费获取攻略

📅 09-30 👁️ 6830