Это нормальное поведение для std :: vector? - PullRequest
1 голос
/ 03 июля 2010

У меня есть std :: vector класса с именем OGLSHAPE.

каждая фигура имеет вектор структуры SHAPECONTOUR, который имеет вектор с плавающей точкой и вектор с вектором double.у него также есть вектор структуры структуры, в котором есть вектор с плавающей точкой.

Изначально моя программа запускалась с использованием 8,7 МБ ОЗУ.Я заметил, что когда я начал их заполнять, добавляя удвоения и числа с плавающей запятой, память быстро росла, а затем выравнивалась.Когда я очищаю вектор OGLSHAPE, используется еще около 19 МБ.Затем, если я добавлю еще около 150 фигур, а затем уберу их, я использую около 19,3 МБ памяти.Я бы подумал, что логично, если бы в первый раз он пошел с 8,7 до 19, что в следующий раз он поднялся бы примерно до 30. Я не уверен, что это такое.Я думал, что это утечка памяти, но теперь я не уверен.Все, что я делаю, это вставляю числа в std :: vectors, ничего больше.Так что я ожидаю вернуть всю свою память.Что может вызвать это?

Спасибо

* отредактируйте, хорошо, фрагментация памяти из-за выделения множества мелких вещей, как это можно решить?

Ответы [ 3 ]

8 голосов
/ 04 июля 2010

Вызов std :: vector <> :: clear () не обязательно освобождает всю выделенную память (это зависит от реализации std :: vector <>). Это часто делается с целью оптимизации, чтобы избежать ненужного выделения памяти.

Чтобы действительно освободить память, удерживаемую экземпляром, просто выполните:

template <typename T>
inline void really_free_all_memory(std::vector<T>& to_clear)
{
    std::vector<T> v;
    v.swap(to_clear);
}

// ...
std::vector<foo> objs;

// ...
// really free instance 'objs'
really_free_all_memory(objs);

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

0 голосов
/ 04 июля 2010

Здесь есть несколько возможных вещей.

Во-первых, в большинстве распространенных библиотек времени выполнения C и C ++ память работает так, что когда она выделяется приложению из операционной системы, она редко возвращается обратно в ОС. Когда вы освобождаете его в своей программе, диспетчер памяти new сохраняет его на случай, если вы снова запросите больше памяти. Если вы это сделаете, он вернет его вам для повторного использования.

Другая причина в том, что сами векторы обычно не уменьшают свой размер, даже если вы их очистите (). Они сохраняют «вместимость», которая была у них на самом высоком уровне, чтобы быстрее их переполнять. Но если вектор когда-либо будет уничтожен, эта память вернется в библиотеку времени выполнения для повторного выделения.

Итак, если вы не уничтожаете свои векторы, они могут сохранять память для вас. Если вы используете что-то в операционной системе для просмотра использования памяти, он, вероятно, не знает, сколько «свободной» памяти ожидает использование в библиотеках времени выполнения, вместо того, чтобы вернуть ее операционной системе.

Причина, по которой использование вашей памяти увеличивается незначительно (а не вовсе), возможно, из-за фрагментации. Это своего рода сложная касательная, но достаточно сказать, что выделение большого количества небольших объектов может усложнить для библиотеки времени выполнения поиск большого фрагмента, когда он в этом нуждается. В этом случае он не может повторно использовать часть памяти, которую он хранит, которую вы уже освободили, потому что она состоит из множества маленьких кусочков. Поэтому он должен пойти в ОС и запросить большой кусок.

0 голосов
/ 04 июля 2010

Используйте правильные инструменты для наблюдения за использованием вашей памяти, например (в Windows) используйте Process Explorer и наблюдайте частные байты.Не смотрите на виртуальное адресное пространство, так как оно показывает наибольший используемый адрес памяти.Фрагментация является причиной большой разницы между обоими значениями.

Также осознайте, что между вашим приложением и операционной системой много слоев:

  • std :: vectorне обязательно сразу освобождает всю память (см. совет hkaiser)
  • Время выполнения C не всегда возвращает всю память операционной системе
  • подпрограммы кучи операционной системы могут не иметь возможности освободитьвся память, потому что он может освободить только полные страницы (из 4 КБ).Если по-прежнему используется 1 байт страницы размером 4 КБ, страница не может быть освобождена.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...