为什么抓不到OOM异常?
Why can't I catch the OOM exception?
我有一个读取大文件以填充 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
我无法捕获异常,为什么?
如果您的程序被 OS 中止,它不会产生任何异常。但是你可以设置一个信号处理程序:
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
的 no-throw 版本。或者 new
可以,但公主在另一座城堡里。
您可能会在最初的问题(崩溃)中遇到两个陷阱。
1.这可能是一个重新分配问题。
当数组已经填满,并且您尝试插入更多时,它会分配一个新数组并从前一个数组复制(移动)数据。所以在复制(移动)完成之前,你最终会得到两个大数组。如果您知道前面字符串的确切数量,您可以尝试预先分配数组以确保不会重新分配。为此使用 QList::reserve()
。
2。像 QList 和 QVector 这样的 Qt 容器可以容纳不超过 2GB 的数据。
如果sizeof(QString)
是8个字节,则最多允许2^28个项目。
如果你尝试存储更多,它最终会崩溃。尝试 std::vector
(使用 reserve
)并检查它是否有效。
毕竟,如果您的系统没有足够的内存来执行任务 - 它没有足够的内存,除了更改算法之外您无能为力。
我有一个读取大文件以填充 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
我无法捕获异常,为什么?
如果您的程序被 OS 中止,它不会产生任何异常。但是你可以设置一个信号处理程序:
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
的 no-throw 版本。或者 new
可以,但公主在另一座城堡里。
您可能会在最初的问题(崩溃)中遇到两个陷阱。
1.这可能是一个重新分配问题。
当数组已经填满,并且您尝试插入更多时,它会分配一个新数组并从前一个数组复制(移动)数据。所以在复制(移动)完成之前,你最终会得到两个大数组。如果您知道前面字符串的确切数量,您可以尝试预先分配数组以确保不会重新分配。为此使用 QList::reserve()
。
2。像 QList 和 QVector 这样的 Qt 容器可以容纳不超过 2GB 的数据。
如果sizeof(QString)
是8个字节,则最多允许2^28个项目。
如果你尝试存储更多,它最终会崩溃。尝试 std::vector
(使用 reserve
)并检查它是否有效。
毕竟,如果您的系统没有足够的内存来执行任务 - 它没有足够的内存,除了更改算法之外您无能为力。