Код, предоставляемый OP, имеет различные недостатки, из-за которых он может не работать:
QFile file("proc/stat");
пытается открыть proc/stat
в текущем каталоге.Если это не случайно корневой каталог, он может не открыть то, что ожидает OP, или просто потерпеть неудачу.Его следует заменить на QFile file("<b>/</b>proc/stat");
, который открывает абсолютный путь (независимо от текущего каталога).
Успех file.open(QIODevice::ReadOnly);
не проверен.QFile::open()
имеет тип возврата bool
и
, возвращающие true в случае успеха;в противном случае - false.
Это следует проверить.
Успех 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()
могут потенциально выделить память, которая может дать сбой, но, опять же, я нене вижу, что может привести к сбою здесь.
Итак, я не имею ни малейшего понятия, что может произойти сбой этого кода, за исключением того, что другой, ранее выполненный код вызвал неопределенное поведение , котороеслучайно начинает становиться видимым в выставленном коде.