2010-09-01 2 views
3

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

В функции рисования сначала создаю новый вектор тех же указателей, а затем начинаем с цикла for, который обрабатывает количество объектов, которые я хочу нарисовать. Внутри этого цикла есть еще один цикл, который определяет, какой объект должен быть нарисован, и когда объект рисуется, его указатель удаляется из вектора с помощью vector.erase(), поэтому одно и то же лицо не будет дважды рисоваться (вот почему я создавая копию вектора, содержащего указатели на объекты).

В любом случае, мой код сам работает, и сущности рисуются так, как я хочу, но у меня, кажется, есть утечка памяти (я могу увидеть, как память в диспетчере задач Windows поднимается на 28 кбит/с).

Утечка памяти остается, даже если я outcomment все, кроме этого:

vector<Entity*> list = ent_list; // ent_list is the list of entity pointers 
list.clear(); 

Так что я думаю, что я что-то не хватает, но я не уверен, что. Я подумал, что, поскольку я не использовал «новый», память позаботилась бы, но, очевидно, это не ... Надеюсь, кто-то может мне помочь!

/Феодор

+0

Как создаются объекты Entity? вы говорите, что вы не используете новый, какой-то библиотечный код использует новое от вашего имени? –

+0

@jk Я думаю, что он означает, что он не использовал новый в самом списке ... – celavek

+1

Task Manager не помогает в определении утечек памяти. Вы можете исправить освобождение всей памяти, и объем используемой памяти все равно не снизится (в диспетчере задач). –

ответ

4

Ссылка на вектор :: ясно говорит: «если элементы вектора являются указателями на объекты, эта функция не будет вызывать соответствующие деструкторы». Вы уверены, что не полагаетесь на это?

+1

Большой, если. Попросите OP, если ваше предположение верно. Угадание является продуктивным. –

+2

+1 Похоже на то, что я догадался.Поскольку вопрос не всегда четко сформулирован, угадание является неотъемлемой частью процесса. Ответ SO может дать вероятный ответ на неопределенный вопрос, а затем уточняться по мере появления дополнительной информации. –

+0

@ Daniel Earwicker: Но задайте вопрос выше, не может быть ошибки вообще. ОП угадывает, что у них есть утечка памяти, основанная на выходе «Диспетчера задач» (это невозможно сделать). Таким образом, эта догадка пытается исправить проблему, которая может фактически не существовать и, таким образом, приводит к большим трудностям для OP, поскольку они начинают удалять указатели, которые не должны быть удалены. Поэтому я считаю это более вредным, чем полезным. Обратите внимание, что этот вопрос получил наименее резкие замечания, поскольку не было попытки фактически удалить указатель. –

1

Нет, стандартные контейнеры стирают только память, которую они создали; std::list.clear(); приведет к аннулированию и удалению самих итераторов, а не памяти, которую вы выделили.

Вы должны позвонить std::list.remove() или std::list.erase() каждому итератору за другим и вручную удалить указатели, которые вы выделили сами.

+1

или, может быть, использовать умные указатели, чтобы он обрабатывался автоматически. –

+1

Нет clear(), который используется в OP, достигнет того же, что и erase (remove()). –

+2

Невозможно сказать, будут ли умные указатели делать что-нибудь полезное. Неясно, управляет ли список ресурсами или просто удерживает указатели на переменные, которые уже управляются. Подобные спекуляции являются контрпродуктивными. Если вы не можете сказать, что происходит, задайте вопрос в разделе комментариев. –

1

Вектор не будет удалять память за указателями. Вам нужно будет удалить каждый объект * перед вызовом clear(), или вы можете использовать «умный контейнер» как boost::ptr_vector.

+2

Как вы можете даже сказать, что указатели нужно управлять. Недостаточно информации, чтобы совершить такой скачок. –

+0

@ Мартин Йорк Я не думаю, что я следую ... действительно вопрос немного нечеткий, но из какой информации возникает вопрос, кажется, что он ожидает, что память, выделенная для указателей, которые его вектор содержит, будет освобождена,() на вектор. Я не уверен, какой прыжок я делаю ... – celavek

+0

Скачок: это даже утечка памяти. Если утечки памяти нет, тогда у него могут быть указатели на объекты, основанные на стеке в векторе (я даже не вижу, чтобы какая-либо ошибка исчезла из английской прозы в вопросе о том, что используется новый). Если вы предложите использовать boost :: ptr_vector <>, то приложение, скорее всего, взорвется и смутит OP. –

0

Самый простой способ исправить это - заменить элемент контейнера на boost::shared_ptr<Element>. Это, вероятно, очистит код, который также использует вектор, и предоставит указатель на лучшую стандартную практику управления памятью по линии.

+2

Вы подходите к выводу, не имеющему никаких доказательств в поддержку вашей теории. Вместо того, чтобы угадывать решение, задайте вопрос OP и попытайтесь подтвердить, что это проблема. –

+0

Спасибо Мартину. Мое утверждение состоит в том, что в исходном вопросе достаточно информации, чтобы указать, что указатели Entity * разделяются между двумя векторами. Выполняя цикл-и-delete перед вызовом clear(), поэтому просто заменяйте утечку сбоем, когда исходный вектор правильно очищен или, возможно, этот вектор не ясен() - ed. В любом случае, владение целевым Entity * неясно. boost :: shared_ptr (или какая-либо альтернатива) адресует именно эту проблему, правильно очищая контейнеры и члены, когда они выходят из области видимости, независимо от того, сколько ссылок на Entity существует. –

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