2015-02-27 2 views
1

Я пишу программу, которая в конечном итоге потребует от меня создать вектор unique_ptrs для объектов пользовательского класса. У меня были некоторые утечки памяти, поэтому я решил удалить пользовательский класс из уравнения и просто попробовать его с помощью unique_ptr.vector unique_ptr не полностью удаляется (утечки памяти)

Когда я пытаюсь создать unique_ptr в стеке, утечек нет. Однако создание вектора unique_ptrs делает утечки. Для удовольствия я также попытался переместить unique_ptr в вектор, чтобы увидеть, что произошло. Мой код ниже (включает в себя проверку памяти МСВС):

#define _CRTDBG_MAP_ALLOC 
#include <stdlib.h> 
#include <crtdbg.h> 

#include <vector> 
#include <memory> 
using namespace std; 

int main() 
{ 
    vector<unique_ptr<int>> testvector; 
    unique_ptr<int> addMe; 

    testvector.emplace_back(move(addMe)); 
    testvector.clear(); 

    _CrtDumpMemoryLeaks(); 
    return 0; 
} 

Когда я закомментируйте все, кроме создания «AddMe», я не получаю утечки.
Когда я прокомментирую все, кроме создания «testvector», я получаю утечку памяти из 8 байтов.
Когда я комментирую emplace_back из «addme» в «testvector», я получаю утечку памяти из 8 байтов.
Когда я ничего не прокомментирую, я получаю утечку памяти 12 байт.
Все ведет себя одинаково, когда я заменяю все «unique_ptr» на «shared_ptr».

Я делаю что-то неправильно или это можно ожидать с помощью векторов умных указателей?

Спасибо!

+0

Попробуйте поместить весь свой код в фигурные скобки, поэтому он будет обладать таким образом, что деструктор вектора будет запущен до того, как вы проверите наличие утечек памяти.'clear()' уничтожит объекты, но вектор может сохранить память (которую вы можете проверить с помощью 'capacity()') для будущего использования. – Cornstalks

+0

@Cornstalks Какой код нужно поместить в фигурные скобки? – PreacherJayne

+0

Все перед '_CrtDumpMemoryLeaks();'. Таким образом, вы можете гарантировать, что 'testvector' полностью уничтожен * до * вы проверяете утечку памяти. – Cornstalks

ответ

1

Как указано в документации на std::vector::clear()

http://www.cplusplus.com/reference/vector/vector/clear/

Удаляет все элементы из вектора (которые разрушаются), в результате чего контейнера с размером 0. Перераспределение не гарантируется и пропускная способность вектора не может измениться из-за вызова этой функции. A Типичная альтернатива, которая заставляет перераспределить использование swap.

Это означает, что элементы удаляются, но внутренняя память, которую использует std::vector, не используется.

Если ваш компилятор поддерживает C++ 11, то вы можете использовать std::vector::shrink_to_fit() для попробовать сделать так, чтобы capacity установлен в size, который после очистки равно 0.

http://www.cplusplus.com/reference/vector/vector/shrink_to_fit/

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

Запрос не имеет обязательной силы, и реализация контейнера является бесплатной , чтобы оптимизировать в противном случае и оставить вектор с большей емкостью , чем его размер.

Это может привести к перераспределению, но не влияет на размер вектора и не может изменять его элементы.

+0

Я думаю, вы пропустили небольшую часть 'shrink_to_fit()': это ** необязательно **. ["Это необязательный запрос для уменьшения емкости() до size(). Это зависит от реализации, если запрос выполнен."] (Http://en.cppreference.com/w/cpp/container/vector/shrink_to_fit) Возможно, что даже после 'shrink_to_fit()' вектор сохраняет некоторую дополнительную память. – Cornstalks

+0

Я добавил эту строку, но, похоже, она не решила все. Утечка памяти уменьшилась с 12 до 8 байтов. – PreacherJayne

+2

Поместите все свои материалы в отдельную функцию и вызовите '_CrtDumpMemoryLeaks()' после возвращения функции. В этом коде не должно быть утечек, просто вы все еще находитесь в кадре функции, и есть еще объекты, которые не были разрушены. – Spo1ler

Смежные вопросы