c++ - 不使用 push_back 的 std::vector bad_alloc

标签 c++ qt vector stdvector bad-alloc

我必须在 Qt 中读取非常大的文本文件,最多 3 GB,并将它们存储为行的集合。 (稍后与他们合作) 我知道线条的大小非常相似,所以我计算了可能的线条数量并在读取文件之前调整了 vector 的大小。但我仍然在大约 3.000.000 行或 ~916 MB reserverd RAM 处得到 bad_alloc。 在程序崩溃时,没有调用任何一个 push_back,因为在 136 MB 的文件中,我的代码将 vector 大​​小调整为 > 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 空字符串....

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

你应该摆脱这个......

result.shrink_to_fit();

...作为一种实现,可能会尝试将字符串从现有缓冲区复制到一个恰好且仅足够大的缓冲区,这样做暂时需要更多内存。

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

关于c++ - 不使用 push_back 的 std::vector bad_alloc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36761674/

相关文章:

c++ - 计算独特项目的更好方法

c++ - OpenCV ANDROID_ABI : not all variants are displayed

c++ - 如何在单行代码中使用大括号语法使用 QJsonObjects 创建 QJsonArray?

c++ - QInputDialog.getItem() 获取项目索引

c++ - 对结构 vector 进行排序

在一行中用零替换初始 NA 值,直到非 NA 列

c++ - cstdlib 无法使用::wcstombs 解析

c++ - 使线程循环 5 次迭代; pthreads、互斥量和信号量

c++ - 将 QDate 转换为 Qstring?

c++ - vector 中的调试断言失败错误