valgrind является сумасшедшим или, это - подлинная утечка памяти итератора карты станд.?

Ну, я очень плохо знаком с Valgrind и профилировщиками утечки памяти в целом. И я должен сказать, что это немного страшно, когда Вы начинаете использовать их причина, Вы не можете прекратить задаваться вопросом, сколько утечек Вы, возможно, оставили нерешенным прежде!

К точке, поскольку я не опытное в программисте C++, я хотел бы проверить, конечно ли, это - утечка памяти или является ею, что Valgrind делает положительную ложь?

typedef std::vector<int> Vector;
typedef std::vector<Vector> VectorVector;
typedef std::map<std::string, Vector*> MapVector;
typedef std::pair<std::string, Vector*> PairVector;
typedef std::map<std::string, Vector*>::iterator IteratorVector;

VectorVector vv;
MapVector m1;
MapVector m2;

vv.push_back(Vector());
m1.insert(PairVector("one", &vv.back()));

vv.push_back(Vector());
m2.insert(PairVector("two", &vv.back()));

IteratorVector i = m1.find("one");
i->second->push_back(10);
m2.insert(PairVector("one", i->second));

m2.clear();
m1.clear();
vv.clear();

Почему это? Разве ясное не должно управлять, называют деструктор каждого объекта и каждого вектора?

Теперь после выполнения некоторых тестов я нашел различные решения утечки:

1) Удаление:

i->second->push_back(10);

2) Добавление:

delete i->second;

3) Удаление второго

vv.push_back(Vector());
m2.insert(PairVector("two", &vv.back()));

Используя решение 2), делает печать Valgring: 10 выделений, 11 освобождает, что в порядке?

Поскольку я не использую новый, почему я должен удалить?

Спасибо, для любой справки!

5
задан 10 revs, 5 users 62% 20 May 2010 в 10:25
поделиться

3 ответа

Здесь у вас неопределенное поведение:

m1.insert(PairVector("one", &vv.back()));

vv.push_back(Vector());

Вставка аннулирует итераторы и ссылки, указывающие на вектор, что означает, что указатель, который вы хранили в карте, также указывает на какую-то черную дыру после вставки.

заставляет Valgring печатать: 10 allocs, 11 frees Is that OK?

Странно, разве он не печатает что-то о double-frees?

Для решения проблемы я бы предложил использовать контейнер, отличный от vector (например, list или deque, чьи мутирующие функции аннулируют итераторы, но не ссылки). Или вы можете хранить указатели (предпочтительно умные, но можно и обычные) на данные в векторе, чтобы адрес фактических данных был стабильным.

1
ответ дан 15 December 2019 в 06:18
поделиться

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

std :: vector <> :: push_back () может сделать недействительными любые итераторы или ссылки на std :: vector <> , если он уже был заполнен. Поскольку std :: vector <> гарантирует, что его содержимое будет храниться непрерывно (так что вы можете использовать его вместо массива), когда ему требуется больше памяти, он должен скопировать себя в другой блок памяти и оригинал становится недействительным.

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

0
ответ дан 15 December 2019 в 06:18
поделиться

В основном эта строка вызывает проблему:

i->second->push_back(10);

Это потому, что i-> second могло стать недействительным, когда вы это сделали:

vv.push_back(Vector());

Второй раз.

Нет необходимости звонить ясно. Когда объект vv выходит за пределы области видимости, он правильно уничтожает все объекты. Также все карты не имеют векторов, поэтому их деструкторы не влияют на векторы, на которые они указывают. Таким образом, использование clear не требуется.

Если вы хотите сохранить то же самое общее решение, создайте список векторов для вашего объекта vv. Тогда вставка в список не повлияет на уже существующих участников, и ваши карты будут работать правильно.

std::list<Vector> vv;  // insertion into this will not invalidate any other members.
                       // Thus any pointers to members you have will not become invalidated.

Лично я думаю, что вы слишком усложняете вещи.
Я думаю, что вы можете добиться тех же результатов, значительно упростив это.
Если на векторы не ссылаются несколько элементов карты, просто поместите вектор в карту.

std::map<std::string, std::vector<int> >    m1;

m1["one"].push_back(10);
m1["two"].push_back(20);
2
ответ дан 15 December 2019 в 06:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: