вектор unique_ptr не удаляется полностью (утечка памяти)

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

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

#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».

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

Спасибо!


person PreacherJayne    schedule 27.02.2015    source источник
comment
Попробуйте поместить весь свой код в фигурные скобки, чтобы его область действия была такой, что деструктор вектора будет запущен до того, как вы проверите наличие утечек памяти. clear() уничтожит объекты, но вектор может сохранить память (что вы можете проверить с помощью capacity()) для будущего использования.   -  person Cornstalks    schedule 27.02.2015
comment
@Cornstalks Какой код мне поставить в фигурные скобки?   -  person PreacherJayne    schedule 27.02.2015
comment
Все до _CrtDumpMemoryLeaks();. Таким образом, вы можете убедиться, что testvector полностью уничтожено, прежде чем вы проверите наличие утечек памяти.   -  person Cornstalks    schedule 27.02.2015
comment
Красиво спасибо! Работал как шарм.   -  person PreacherJayne    schedule 27.02.2015


Ответы (1)


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

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

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

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

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

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

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

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

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

person JustSomeGuy    schedule 27.02.2015
comment
Я добавил эту строку, но, похоже, это не решило все. Утечка памяти уменьшилась с 12 до 8 байт. - person PreacherJayne; 27.02.2015
comment
Поместите все свои вещи в отдельную функцию и вызовите _CrtDumpMemoryLeaks() после возврата функции. В этом коде не должно быть утечек, просто вы все еще находитесь в кадре функции и все еще есть объекты, которые не были уничтожены. - person JustSomeGuy; 27.02.2015
comment
@Cornstalks, спасибо, исправил в ответе - person JustSomeGuy; 27.02.2015
comment
Помещение его в отдельную функцию сработало даже без сжатия. Я обязательно буду иметь в виду усадку! - person PreacherJayne; 27.02.2015