Данные, считанные из файла, занимают намного больше памяти, чем размер файла

Я записал некоторые данные в файл следующим образом:

result = new QHash<QPair<int, int>, QVector<double> >;
QFile resfile("result.txt");
resfile.open(QIODevice::WriteOnly | QIODevice::Append);
QDataStream out(&resfile);
while(condition)
{
QString s=" something";
out<<s;
res->insert(QPair<int, int>(arange,trange),coeffs);
out<<res;
}

Файл получился равным 484 МБ. После этого я прочитал это в цикле:

QString s;
QVector<QHash<QPair<int, int>, QVector <double> > >    thickeness_result;
QFile resfile("result.txt");
resfile.open(QIODevice::ReadOnly);
QDataStream out(&resfile);
while (!out.atEnd())
{
 thickeness_result.resize(thickeness_result.size()+1);
out>>s>>thickness_result.last();   
 }

Пока выполняется этот цикл чтения, я вижу, что в диспетчере задач моя программа начинает занимать около 1300 МБ памяти, и после этого я получаю сообщение об ошибке «В файле text\qharfbuzzng.cpp, строка 626: нехватка памяти». Мой вопрос: это нормально, что программа начинает занимать больше, чем 2-кратный размер файловой памяти, и я должен читать ее кусками, или я делаю что-то не так?


person Danilla Malyshkin    schedule 12.12.2015    source источник


Ответы (1)


ВНИМАНИЕ Все нижеследующее предполагает, что QVector ведет себя как std::vector

Да, это нормально. Происходит следующее: когда у вас есть 1024 элемента и вы хотите прочитать еще один, вызов resize выделяет емкость для 2048 элементов, перемещает первые 1024 элемента, а затем создает 1025-й элемент. Он уничтожает старый массив и возвращает память в кучу (но не в операционную систему). Затем, когда вы приходите к чтению 2049-го элемента, он делает все это снова, только на этот раз выделяя 4096 элементов. В куче есть фрагмент из 1024 элементов, но это бесполезно, когда вам нужно 4096. Теперь у вас есть фрагменты из 1024, 2048 и 4096 элементов в куче (два из которых бесплатны и доступны для повторного использования).

Повторяйте, пока не прочитаете файл. Вы увидите, что у вас в итоге (примерно) вдвое больше размер файла.

Первое правило — «не беспокойтесь об этом» — обычно это не проблема. Впрочем, для вас это явно так.

Можно ли перейти на 64-битную программу? Это должно устранить проблему.

Другой вариант — угадать, сколько элементов у вас есть (по размеру файла), и вызвать .reserve для вектора в начале.

person Martin Bonner supports Monica    schedule 12.12.2015
comment
Спасибо за ваше объяснение! Попробую найти обходной путь =) - person Danilla Malyshkin; 12.12.2015
comment
Резервирование никак не помогает, к сожалению. - person Danilla Malyshkin; 12.12.2015
comment
В этом случае у вас есть выбор: конвертировать в 64-битную версию; читать кусками. - person Martin Bonner supports Monica; 12.12.2015