0

假设您想从大型文本文件(~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));

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

  1. 为什么istringstream会这样;
  2. 如果是预期行为,如何完成上述任务?

谢谢

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

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

完整的编译就绪代码(添加标题):

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;
}
4

2 回答 2

0

我严重怀疑这不是 istringstream 问题(尤其是考虑到您在循环外使用 iLine 构造函数的结果相同)。

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

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

于 2013-01-31T07:15:48.810 回答
0

vector<>内存呈几何增长。一个典型的模式是它在需要增长时将容量翻倍。如果您的循环在这样的阈值之后立即结束,那么这可能会留下大量分配但未使用的额外空间。完成后,您可以尝试调用shrink_to_fit()每个向量。

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

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

所以我假设你看到的正常行为vector<>

于 2013-01-31T07:17:53.870 回答