istringstream () (возможно) утечка памяти

Предположим, вы хотите прочитать данные из большого текстового файла (~ 300 МБ) в массив векторов: 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 (iLine.str(""); iLine.clear();) вызывает тот же порядок взрыва памяти, а также.
Вопросы, которые возникают:

  1. Зачем istringstream ведет себя так;
  2. если это предполагаемое поведение, как вышеуказанная задача может быть выполнена?

Спасибо

РЕДАКТИРОВАТЬ: Что касается 1-го ответа, я очищаю память, выделенную массивом позже в коде:

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

0

Решение

vector<> растет память геометрически. Типичным примером является то, что он удваивает емкость всякий раз, когда ему нужно расти. Это может оставить много дополнительного пространства выделенным, но неиспользованным, если ваш цикл заканчивается сразу после такого порога. Вы можете попробовать позвонить shrink_to_fit() на каждом векторе, когда вы закончите.

Кроме того, память, выделенная распределителями C ++ (или даже просто malloc()) часто не возвращается в ОС, но остается во внутреннем пуле свободной памяти процесса. это может привести к дальнейшему очевидному росту. И это может привести к результатам shrink_to_fit() быть невидимым извне процесса.

Наконец, если у вас много маленьких строк («двузначных чисел»), накладные расходы stringобъект может быть значительным. Даже если в реализации используется оптимизация с небольшими строками, я предполагаю, что типичная строка использует не менее 16 или 24 байтов (размер, емкость, указатель данных или небольшой строковый буфер) — вероятно, больше на платформе, где size_type составляет 64 бита. Это много памяти для 3 байтов полезной нагрузки.

Поэтому я предполагаю, что вы видите нормальное поведение vector<>

0

Другие решения

Я серьезно подозреваю, что это не проблема istringstream (особенно если учесть тот же результат с конструктором iLine вне цикла).

Возможно, это нормальное поведение std :: vector. Чтобы проверить это, как насчет того, чтобы запустить те же строки, но закомментируйте: Data[i].push_back(u);, Посмотрите, растет ли ваша память таким образом. Если это не так, то вы знаете, где проблема ..

Зависит от вашей библиотеки, vector :: push_back будет увеличивать свою емкость в 1,5 (Microsoft) или 2 (glib) раза каждый раз, когда ему нужно больше места.

0

По вопросам рекламы [email protected]