C++ std::bad_alloc 错误

5

我在编写一个C++程序(C++ 98)。它会读取一个包含很多行(10000行)的文本文件,这些行是用tab键分隔的值,然后我将其解析成一个Vector of Vector对象。但是,它似乎只能处理一些较小的文件,而其中一个文件却给了我以下错误(该文件有10000行,大小为90MB)。我猜想这是与内存相关的问题?

错误信息

terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Abort

代码

void AppManager::go(string customerFile) {

    vector<vector<string> > vals = fileReader(customerFile);

    for (unsigned int i = 0; i < vals.size();i++){

        cout << "New One\n\n";

        for (unsigned int j = 0; j < vals[i].size(); j++){

            cout << vals[i][j] << endl;
        }

        cout << "End New One\n\n";
    }
}

vector<vector<string> > AppManager::fileReader(string fileName) {

    string line;
    vector<vector<string> > values;

    ifstream inputFile(fileName.c_str());

    if (inputFile.is_open()) {

        while (getline(inputFile,line)) {

            std::istringstream iss(line);
            std::string val;
            vector<string> tmp;

            while(std::getline(iss, val, '\t')) {

                tmp.push_back(val);
            }

            values.push_back(tmp);
        }

        inputFile.close();
    }
    else {

        throw string("Error reading the file '" + fileName + "'");
    }

    return values;
}

1
你有一个堆栈跟踪能显示bad_alloc被抛出的位置吗?(另外,你有多少可用的内存?) - us2012
我正在使用我所在大学的服务器,但我无法控制它。这个服务器正在破坏Solaris系统,而我的应用程序需要在其上运行。数据集是由他们提供的。 - Achintha Gunasekara
我该如何获取堆栈跟踪?抱歉,我是C++的新手。 - Achintha Gunasekara
要获取堆栈跟踪,请在调试器下运行程序。当异常被抛出时,调试器将返回回溯信息。您的平台上可能有 gdb,Solaris 也有 dbx。通常,您可以通过在命令行上提供要调试的可执行文件,然后发出 run 命令来使用调试器。不过,手册是您的好朋友。 - Kuba hasn't forgotten Monica
1个回答

7
你的代码没有问题,只是在一个可能有内存限制、旧编译器和旧C++库的平台上运行。这些都会对你造成影响。你需要进行微观优化 :(
以下是你可以做的事情,从最容易开始:
1. 首先运行一遍文件,只计算行数。然后使用values.resize(numberOfLines),回到开头,然后再读取值。当然,你不会再使用values.push_back,而是使用values[lineNumber] = tmp。在添加到向量时调整values向量的大小可能会使你的进程在临时基础上需要的内存量增加一倍以上。
2. 在行末,执行tmp.resize(tmp.size() - 它将缩小向量以适应数据。
3. 通过将所有值存储在一个向量中,可以减少现有代码中的开销。
- 如果每行具有不同数量的元素,但稍后按顺序访问它们,则可以将空字符串作为内部分隔符进行存储,它可能比向量的开销更小。 - 如果每行具有相同数量的值,则通过行拆分添加不必要的开销 - 你知道每行中第一个值的索引,它只是lineNumber * valuesPerLine,其中第一行的编号为0
4. 内存映射文件。将每个单词的开头和结尾存储在一个向量的结构元素中,如果需要按行拆分,则可以添加行号。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接