1

我正在编写一个应用程序,在该应用程序中我从 csv 文件中读取值。每行都被分割,逗号存储在一个向量中。每行有 4 个值。然后我将每个值存储到另一个向量。csv 文件有 5.795.857 行。所以在我的结构中我想存储 4*5.795.857 值。问题是应用程序崩溃了。正如我在调试器中看到的那样,我大约在 405.000 行处崩溃。我知道我的电脑有点旧,但我认为它应该能够存储这么多的值。我在 WindowsXP 32 位上运行 Qt5,我有 1GB 内存。

我是 Qt 和 c++ 编程的新手,但作为 Java 开发人员,当我遇到此类问题时,我会增加堆大小。你认为这是我的问题吗?如果是,我如何增加 Qt5 的堆大小?

这是我读取文件并将其存储在数据结构中的代码

std::vector  < std::vector < QString> >  Server::loadCsvFile( const char* path )
{
  vector <QString> temp;
  vector  <vector <QString> > dataFlow;
  string dataString;
  QString row;
  ifstream dataFile( path );

  int stopCounter = 0;

  //while((dataFile.good()) && (stopCounter < 1095))
  while (dataFile.good())
  {
    stopCounter++;
    getline( dataFile, dataString );
    row = QString::fromStdString( dataString );
    //cout << "counter: " << stopCounter << "\n";
    QStringList rowList = row.split( "," );

    for(  int i=0; i < rowList.size(); i++ )
    {
      temp.push_back( rowList.at(i));
    }

    dataFlow.push_back( temp );
    temp.clear();
    rowList.clear();
  }

  dataFile.close();
  dataFlow.pop_back();

  return dataFlow;
}

到目前为止,我做了一些更改以查看这解决了我的问题,但没有。这就是我的代码知道的样子:

std::vector < QStringList > Server::loadCsvFile2( const char* path )
{
    std::vector < QStringList > dataFlow;
    QFile file(path);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        throw std::runtime_error("Can't open the file " +
                                 std::string(path));
    QTextStream in(&file);
    int counter = 0;
    while (!in.atEnd())
    {
        counter++;
        dataFlow.emplace_back(in.readLine().split(","));
        cout << counter << "\n";
    }
    return dataFlow;
}
4

1 回答 1

0

基本上,astd::vector包含三个元素:

  • 一个尺寸
  • 元素数组
  • 能力

容量是向量当前可以容纳的元素数量,它是数组的实际大小(在 RAM 中)。大小是向量中真正拥有的元素数量。例如,当您创建一个 empty 时vector<int>,它的大小为 0,容量为 10(或其他东西,我不知道)并且数组正在消耗10 * sizeof(int). 如果您push_back是一个值,则大小为 1,但容量或数组的实际大小没有改变。

但是当你的向量中有 10 个元素并尝试添加一个时,会发生一些事情:实际数组已满 ( vec.size() == vec.capacity()),因此算法必须扩展该容量:

  • 容量价值翻倍,
  • 分配一个实际大小为新容量的新数组;换句话说,分配20 * sizeof(int)字节,
  • 将旧数组的内容复制到新数组,
  • 旧数组消耗的空闲内存,
  • 现在,像往常一样添加项目,因为有可用空间。

当然,您现在最多可以添加 20 项,添加 21 项将使算法分配 40 项,添加 41 项将分配 80 项,依此类推。

通常,您并不真正关心这些内部细节。但是,当您向向量添加大量项目时,事情就会开始出现问题。向量增长得越多,新的分配和副本就越需要时间并消耗 RAM。在您的情况下,我怀疑您的第 405 001 行使算法需要分配 810 000 个元素,并从第一个元素复制到第二个元素,并且由于 RAM 运行非常低,您的操作系统正在将其部分写入磁盘,这已经死了减缓。

您希望数组的初始容量足够大以减少重新分配的发生。您可以做的是调用该reserve方法并给它一个足够大的数字以避免过多的分配。但是,即使这样,恐怕您也可能没有足够的 RAM 来实现该过程。

于 2013-05-22T15:20:10.007 回答