istringstream()(可能)内存泄漏

时间:2013-01-31 06:51:14

标签: c++ file memory-management readfile istringstream

假设您要将大文本文件(~300mb)中的数据读取到向量数组:vector<string> *Data(假设列数已知)。

//file is opened with ifstream; initial value of s is set up, etc...


Data = new vector<string>[col];
string u;
int i = 0;

do
{       
    istringstream iLine = istringstream(s);

    i=0;
    while(iLine >> u)
    {
        Data[i].push_back(u);
        i++;
    }
}
while(getline(file, s));

此代码适用于小文件(&lt; 50mb),但在读取大文件时,内存使用量呈指数级增长。我很确定问题是每次在循环中创建istringstream个对象。但是,在两个循环之外定义istringstream iLine;并将每个字符串放入iLine.str(s);流并在内部while循环(iLine.str(""); iLine.clear();)之后清除流导致同样的内存爆炸顺序。 出现的问题:

  1. 为什么istringstream表现得这样;
  2. 如果是预期的行为,如何完成上述任务?
  3. 谢谢

    编辑:关于第一个答案,我稍后在代码中清理数组分配的内存:

    for(long i=0;i<col;i++)
        Data[i].clear();
    delete []Data;
    

    完整的COMPILE-READY CODE(添加标题):

    int _tmain(int argc, _TCHAR* argv[])
    {
    ofstream testfile;
    testfile.open("testdata.txt");
    
    srand(time(NULL));
    
    for(int i = 1; i<1000000; i++)
    {
        for(int j=1; j<100; j++)
        {
            testfile << rand()%100 << " ";
        }
    
        testfile << endl;
    }
    
    testfile.close();
    
    vector<string> *Data;
    
    clock_t begin = clock();
    
    ifstream file("testdata.txt"); 
    
    string s;
    
    getline(file,s);
    
    istringstream iss = istringstream(s);
    
    string nums;
    
    int col=0;
    
    while(iss >> nums)
    {
        col++;
    }
    
    cout << "Columns #: " << col << endl;
    
    Data = new vector<string>[col];
    
    string u;
    int i = 0;
    
    do
    {
    
        istringstream iLine = istringstream(s);
    
        i=0;
    
        while(iLine >> u)
        {
            Data[i].push_back(u);
            i++;
    
        }
    
    }
    while(getline(file, s));
    
    cout << "Rows #: " << Data[0].size() << endl;
    
    for(long i=0;i<col;i++)
            Data[i].clear();
        delete []Data;
    
    clock_t end = clock();
    
    double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
    
    cout << elapsed_secs << endl;
    
    getchar();
    return 0;
    }
    

2 个答案:

答案 0 :(得分:0)

我严重怀疑这不是istringstream问题(特别是,考虑到你在循环之外的iLine构造函数有相同的结果)。

可能这是std :: vector的正常行为。为了测试它,你如何运行完全相同的行,但注释掉:Data[i].push_back(u);。看看你的记忆是否以这种方式增长。如果没有,那么你知道问题出在哪里..

取决于您的库,vector :: push_back每次需要更多空间时,其容量将扩大1.5倍(微软)或2倍(glib)。

答案 1 :(得分:0)

vector<>以几何方式增长记忆。典型的模式是,只要需要增长,它就会使容量翻倍。如果您的循环在此阈值之后立即结束,那么可能会留下大量额外空间但未使用。完成后,您可以尝试在每个向量上调用shrink_to_fit()

此外,由C ++分配器(甚至是普通malloc())分配的内存通常不会返回给操作系统,而是留在进程内部空闲内存池中。这可能会导致进一步明显的增长。并且它可能导致shrink_to_fit()的结果在流程外部不可见。

最后,如果你有很多小字符串(“2位数字”),string对象的开销可能相当大。即使实现使用小字符串优化,我也假设一个典型的字符串使用不少于16或24个字节(大小,容量,数据指针或小字符串缓冲区) - 在{{1}的平台上可能更多是64位。这是3字节有效载荷的大量内存。

所以我假设你看到了size_type

的正常行为