Освобождение памяти boost::shared_ptr из std::vector

Я пытаюсь освободить память boost::shared_ptr<std::vector<std::vector<std::vector<int> > > >, используя следующий код:

vec->clear();
std::vector<std::vector<std::vector<int> > > (*vec).swap(*vec);

Но почему-то не работает. Я проверил с помощью команды htop, и используемая память такая же, как я никогда не освобождал объект.

Затем я попытался выпустить каждый вектор отдельно, например:

for (auto it1 : *vec) 
{
    for (auto it2 : it1)
    {
        it2.clear();
        std::vector<int>(it2).swap(it2);
    }
    it1.clear();
    std::vector<int>(it1).swap(it1);
}   

Но все равно потребляет такое же количество памяти.

Я делаю что-то неправильно? Возможно, это связано с shared_ptr, потому что я уже выпускал векторы без указателей, и это работало.

Обновить

Shared_ptr не выйдет за пределы области видимости, поскольку является членом класса объекта, который продолжает выполняться в спящем потоке.


person Jcao02    schedule 21.07.2014    source источник
comment
vec.release() должен уничтожить все. Но что бы вы ни делали, память, вероятно, будет высвобождена в кучу процесса, а не обратно в ОС (хотя детали зависят от платформы). Вам понадобится более глубокая магия, если вы действительно хотите такого уровня контроля.   -  person Mike Seymour    schedule 21.07.2014
comment
Не используйте инструменты ОС, чтобы определить, что внутри делает C++ менеджер кучи.   -  person PaulMcKenzie    schedule 21.07.2014
comment
Какой тип vec? Это не может быть shared_ptr<...>, потому что тогда ваш код не скомпилируется. И вы можете рассмотреть Boost.MultiArray вместо вектора вектора векторов.   -  person Praetorian    schedule 21.07.2014
comment
какова цель шаблона var.clear(); type(var).swap(var); ?   -  person Johan    schedule 21.07.2014
comment
@Johan clear вызовет деструктор каждого объекта в векторе, а swap уменьшит размер вектора до 0 (поскольку объектов больше нет)   -  person Jcao02    schedule 21.07.2014
comment
I've released vectors without pointers before and it worked Вам не гарантируется, что это работает. На самом деле это диспетчер кучи компилятора, который управляет взаимодействием между использованием памяти кучи вашим приложением и ОС. Может быть, простая причина заключается в том, что менеджер кучи понимает, что вы можете снова выделить память, поэтому все, что ему нужно сделать, это настроить пару внутренних указателей в своих структурах данных вместо того, чтобы делать дорогостоящий вызов ОС для освобождения (и затем выделения снова). ).   -  person PaulMcKenzie    schedule 21.07.2014
comment
@Jcao02 Я не думаю, что это гарантировано. Я даже думаю, что для того, чтобы итератор оставался действительным, вы не можете освободить буфер. shrink_to_fit кажется гораздо более подходящим для этой цели.   -  person Johan    schedule 21.07.2014
comment
@Praetorian, да, это... это boost::shared_ptr‹vector...›, и это работает. Я использую GCC 4.7.   -  person Jcao02    schedule 21.07.2014
comment
@PaulMcKenzie, что я должен использовать, чтобы определить это?   -  person Jcao02    schedule 21.07.2014
comment
@ Jcao02 Jcao02 Как эта конструкция копирования должна работать, если vec является shared_ptr? std::vector<std::vector<std::vector<int> > >(vec) — обратите внимание, что в приведенном выше примере у вас есть дополнительные >.   -  person Praetorian    schedule 21.07.2014
comment
Но сжатие_в_подгонку — необязательный запрос, поэтому его можно игнорировать, не так ли? @Йохан   -  person Jcao02    schedule 21.07.2014
comment
@Praetorian, моя ошибка, я использую значение умного указателя (* vec)   -  person Jcao02    schedule 21.07.2014
comment
@ Jcao02 - Это может показаться легкомысленным, но руководствуйтесь здравым смыслом. Вы знаете, что код не дает утечки памяти, верно? Так что доверяйте диспетчеру кучи вашего компилятора контролировать ситуацию. Диспетчер кучи будет знать в эффективный момент времени, когда на самом деле вызывать ОС для освобождения памяти. Если у вас действительно была утечка памяти, то да, инструменты ОС в конце концов покажут, что что-то не так. Но вы не можете использовать эти инструменты для микроанализа операций диспетчера кучи C++.   -  person PaulMcKenzie    schedule 21.07.2014
comment
@ Jcao02 Jcao02 Извините, пытаясь лучше понять ваш шаблон clear/build/swap, я вижу, что он работает. Я сказал что-то глупое об итераторе, потому что они действительно будут сохранены в замененном векторе, который будет уничтожен. Но мне кажется, что это чересчур.   -  person Johan    schedule 21.07.2014
comment
@ Jcao02 Хорошо, теперь попробуйте распечатать vec->capacity() до и после swap   -  person Praetorian    schedule 21.07.2014
comment
@Praetorian, вы имеете в виду первую версию вызова очистки с помощью vec, или это необходимо делать со всеми внутренними векторами?   -  person Jcao02    schedule 21.07.2014
comment
@Jcao02 Jcao02 Просто добавьте его в существующий код, как показано выше. Внутренним векторам будет трудно что-либо содержать, если vec->capacity() == 0 после swap :)   -  person Praetorian    schedule 21.07.2014


Ответы (1)


Если у вас есть std::shared_ptr<std::vector>> и вы хотите его удалить:

std::shared_ptr<std::vector<T>> ptr = ...;
ptr.reset();

Если у вас есть std::vector<std::shared_ptr<T>> и вы хотите его очистить:

std::vector<std::shared_ptr<T>> vec = ...;
vec.clear();

Если у вас есть std::vector<T> и вы хотите vec.capacity() == vec.size():

std::vector<T> vec = ...;
vec.shrink_to_fit(); // or: std::vector<T>(vec).swap(vec);

Если вы обеспокоены тем, что htop не показывает уменьшенный объем памяти, выделенной процессу, давайте просто отметим это как дубликат этого сообщения: vector‹string› не очищает память после выхода из области видимости

person Bill Lynch    schedule 21.07.2014
comment
сброс гарантирует освобождение памяти каждого вектора? - person Jcao02; 21.07.2014
comment
Если вы вызываете ptr.reset(), когда ptr.use_count() == 1 и ptr.get() != NULL, то деструктор будет вызываться для содержащегося std::vector<T>. - person Bill Lynch; 21.07.2014
comment
@Jcao02: Ваш вопрос на самом деле: Правильно ли работает деструктор std::vector‹std::vector‹int››? - person Bill Lynch; 21.07.2014
comment
Нет, я подумал, может быть, мне нужно сделать что-то особенное из-за указателей и множества векторов внутри указателей. - person Jcao02; 21.07.2014