我正在为读取CPU /内存状态编写一些Qt应用程序。但是,出现一些错误:无法打开proc / stat设备。应用程序崩溃了。请告诉我哪里出了问题?在下面,我还将提供一段代码。
QVector<qulonglong> SysInfoLinuxImpl::cpuRawData()
{
QFile file("proc/stat");
file.open(QIODevice::ReadOnly);
QByteArray line = file.readLine();
file.close();
qulonglong totalUser = 0, totalUserNice = 0, totalSystem = 0, totalIdle = 0;
std::sscanf(line.data(), "cpu %llu %llu %llu %llu", &totalUser, &totalUserNice, &totalSystem, &totalIdle);
QVector<qulonglong> rawData;
rawData.append(totalUser);
rawData.append(totalUserNice);
rawData.append(totalSystem);
rawData.append(totalIdle);
return rawData;
}
答案 0 :(得分:0)
OP公开的代码可能会导致多种缺陷:
QFile file("proc/stat");
尝试在当前目录中打开proc/stat
。如果这不是偶然的根目录,则可能无法打开OP期望的目录,或者只是失败。
应该用QFile file("/proc/stat");
代替,它打开一个绝对路径(独立于当前目录)。
file.open(QIODevice::ReadOnly);
的成功未得到测试。 QFile::open()
的返回类型为bool
和
成功则返回true;否则为假。
应该选中它。
也未检查std::sscanf(line.data(), "cpu %llu %llu %llu %llu", &totalUser, &totalUserNice, &totalSystem, &totalIdle);
是否成功。 std::sscanf()
的返回类型为int
并返回
成功分配的接收参数的数量(如果在分配第一个接收参数之前发生匹配失败,则为零);如果在分配第一个接收参数之前发生输入失败,则为EOF。
我将OP的示例代码转换为MCVE,并添加了一些诊断程序来演示问题:
#include <QtWidgets>
namespace SysInfoLinuxImpl {
template <bool FIX = false>
QVector<qulonglong> cpuRawData();
} // namespace SysInfoLinuxImpl
template <bool FIX = false>
QVector<qulonglong> SysInfoLinuxImpl::cpuRawData()
{
QFile file(FIX ? "/proc/stat" : "proc/stat");
file.open(QIODevice::ReadOnly);
QByteArray line = file.readLine();
file.close();
qDebug() << "line:" << line;
qulonglong totalUser = 0, totalUserNice = 0, totalSystem = 0, totalIdle = 0;
int ret =
std::sscanf(line.data(), "cpu %llu %llu %llu %llu", &totalUser, &totalUserNice, &totalSystem, &totalIdle);
qDebug() << "sscanf(): " << ret;
qDebug() << "totalUser: " << totalUser;
qDebug() << "totalUserNice:" << totalUserNice;
qDebug() << "totalSystem: " << totalSystem;
qDebug() << "totalIdle: " << totalIdle;
QVector<qulonglong> rawData;
rawData.append(totalUser);
rawData.append(totalUserNice);
rawData.append(totalSystem);
rawData.append(totalIdle);
return rawData;
}
int main()
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
// check original code
qDebug() << "with 'proc/stat'";
SysInfoLinuxImpl::cpuRawData();
// check fixed code
qDebug() << "with '/proc/stat'";
SysInfoLinuxImpl::cpuRawData<true>();
return 0;
}
我在cygwin(在Windows 10上)上编译并测试了代码,并得到以下输出:
Qt Version: 5.9.4
with 'proc/stat'
QIODevice::read (QFile, "proc/stat"): device not open
line: ""
sscanf(): -1
totalUser: 0
totalUserNice: 0
totalSystem: 0
totalIdle: 0
with '/proc/stat'
line: "cpu 137982341 0 106654637 1152709669\n"
sscanf(): 4
totalUser: 137982341
totalUserNice: 0
totalSystem: 106654637
totalIdle: 1152709669
最后,我不太确定为什么OP会这么说
应用程序崩溃了。
我坚信崩溃不会在公开代码中发生(而是在其他地方)。我认为是因为:
QByteArray line = file.readLine();
(尝试从无法打开的file
读取时)会导致一个空数组(QIODevice::readLine()
,QByteArray
),甚至会导致一个空数组始终确保数据后跟一个'\ 0'终止符。
因此,即使未分配任何变量,对line.data()
中std::sscanf(line.data(), "cpu %llu %llu %llu %llu", &totalUser, &totalUserNice, &totalSystem, &totalIdle);
的访问也应该是安全的。即使sscanf()
失败,变量也会被初始化并具有定义的值。
rawData.append()
的最终调用可能会分配内存,这可能会失败,但是再次,我看不到这里会崩溃。
因此,除了其他先前执行的代码导致Undefined Behavior意外地在公开代码中变得可见之外,我不知道这段代码可能会崩溃的原因。