为什么我无法捕获 OOM 异常?



我有一个函数,它读取一个大文件来填充QStringList。程序崩溃可能是因为内存不足,因为如果我使用一个小文件,程序运行良好。我试图通过捕捉异常来调试问题。

QStringList readlargefile(QString filename)
{
QStringList result;
QFile file(filename);
if (!file.open(QIODevice::ReadOnly))
{
qDebug()<<"cannot open file: "<<filename;
return result;
}
QTextStream in(&file);
in.setCodec("UTF-8");
QString line;
while(in.readLineInto(&line))
{
if(!line.isEmpty())
result<<line;
}
file.close();
return result;
}

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QStringList result;
try
{
qDebug()<<"reading file";
result=readlargefile("largefile.txt");
}
catch(...) {
qFatal("got exception");
}
}

输出为:

reading file
Killed

我抓不到异常,为什么?

如果您的程序被操作系统中止,它将不会生成任何异常。但是你可以设置一个信号处理程序:

void signalHandler(int)
{
//...
}
int main(int argc, char* argv[])
{
signal(SIGINT  , signalHandler);
signal(SIGTERM , signalHandler);
#ifdef Q_OS_WIN
signal(SIGBREAK, signalHandler);
#endif

无法捕获std::bad_alloc的原因是Qt可能使用了::new的非抛出版本。或者new可以,但公主在另一座城堡里。

在最初的问题(崩溃(中,你可能会遇到两个陷阱。

1.这可能是一个重新分配的问题

当阵列已经填满,并且您尝试插入更多时,它会分配一个新阵列,并从上一个阵列复制(移动(数据。因此,在复制(移动(完成之前,您最终会得到两个大数组。如果您知道前面字符串的确切数量,可以尝试预分配数组,以确保不会重新分配。使用QList::reserve()

2.Qt容器,如QList和QVector,可以容纳不超过2GB的数据

如果sizeof(QString)是8个字节,则不允许超过2^28个项目。

如果你试图存储更多,它最终会崩溃。尝试std::vector(使用reserve(并检查它是否有效。

毕竟,如果你的系统没有足够的内存来执行任务——它没有足够的存储器,你对此无能为力,只能改变你的算法。

最新更新