std :: vector bad_alloc没有使用push_back

时间:2016-04-21 06:46:52

标签: c++ qt vector stdvector bad-alloc

我必须在Qt中读取非常大的文本文件,最多3 GB,并将它们存储为一组行。 (稍后与他们合作) 我知道线条的大小非常相似,所以我在计算可能的线条数量并在读取文件之前调整矢量大小。但我仍然在大约3.000.000行或~916 MB保存的RAM中获得bad_alloc。 在程序崩溃的时候,没有单个push_back被调用,因为在136 MB文件中,我的代码将向量调整为> 7.000.000。

我运行Windows 10 x64,内存为8 GB,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文件的情况下从main方法中读取文件,则不会发生bad_alloc。如果我加载qml并读取文件,qt表示没有足够的内存来加载qml库。

编辑2: 因此,如果没有QML,崩溃将在8.000.000行和1.5 GB预留空间中出现。

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

1 个答案:

答案 0 :(得分:2)

   result.resize(size);

我认为你想reserve(size),因为resize()相当于push_back - size空字符串....

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

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

result.shrink_to_fit();

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

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