繁体   English   中英

不使用push_back的std :: vector bad_alloc

[英]std::vector bad_alloc without using push_back

我必须读取Qt中最大为3 GB的非常大的文本文件,并将它们存储为行的集合。 (稍后再使用)我知道这些行的大小非常相似,因此我在读取文件之前计算了可能的行数并调整了向量的大小。 但是我仍然在约3.000.000行或约916 MB备用RAM上获得bad_alloc。 程序崩溃时,没有调用单个push_back,因为在136 MB文件中,我的代码将向量的大小调整为> 7.000.000。

我正在使用8 GB RAM运行Windows 10 x64,4,9是免费的。

这是我的尝试:

QString filepath = "K://_test//test.txt";
QFile qfile(filepath)

if (!qfile.open(QIODevice::ReadOnly | QIODevice::Text)) {
   return false;
}

// All lines have similar size, so try to calculate the amount from filesize
QFileInfo info(qfile);
long size = info.size() / 1024; // in kb

size = size / 0.0453333; // Cutting decimals is ok at this amount

std::vector<QString> result;

if (size > 0) {
   // Replaced: result.resize(size);
   result.reserve(size);
}

//Reading
QTextStream in(&qfile);
QString line = "";
long cnt = 0;

while (!in.atEnd()) {
   line = in.readLine();

   if (line.isEmpty() == false)
   {
      result.push_back(line);

      /**Replaced:
      if (cnt > (size - 1)) {
         result.push_back(line);
      }
      else {
         result.at(cnt) = line;
      }*/

      cnt++;
   }
}

// Removed: result.shrink_to_fit();

file->setLines(result);
// file is a object with only the filepath and the lines in it.

编辑:我只是想出了一些办法。 我(必须)使用QML,而我的QML创建了读取文件的类实例。 如果我从主方法读取文件而未加载.qml文件,则不会出现bad_alloc问题。 如果我加载qml并读取文件,则qt表示没有足够的内存来加载qml库。

编辑2:因此,没有QML,崩溃发生在8.000.000行和1,5 GB的保留空间上。

编辑3:我将上面的代码更新为当前状态。

   result.resize(size);

我认为您想在此处reserve(size) ,因为resize()等效于push_back -ing size空字符串设置size ...。

此外,请记住, vector仅包含固定大小的QString字符串管理对象:它们大概包含指针,并且当将实际文本分配给它们时,它们将动态分配用于存储该文本的内存。 这很可能是您bad_alloc的来源。 这样的分配必须在in.readLine();内部in.readLine();

您可能应该摆脱这个...

result.shrink_to_fit();

...因为一种实现可能会尝试将字符串从现有缓冲区精确地复制到一个且仅足够大,因此暂时需要更多的内存。

如果要以极低的开销在内存中保留大量文本,建议您使用内存映射文件。 如果对您有用,则可以保留指向每行第一个字符的指针vector

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM