push_backing в список указателей вызывает утечку памяти - PullRequest
0 голосов
/ 05 октября 2011

Я пытаюсь найти утечку памяти с помощью Visual Leak Detector. Он показывает мне m_neighbors.push_back(ent); вызывает утечку.

(краткое callstack = NeighborCalculatorDummy -> foreach -> list -> allocate)

Я использую его как NeighborCalculatorDummy<Entity *>, поэтому pushback должен просто вставить указатель в список без какого-либо выделения. Все указатели на сущности, которые приходят через addEntity, удаляются в другом месте кода ...

Как push_back может вызвать утечку?

template <typename entity_type>
class NeighborCalculatorDummy
{
public:
    inline void addEntity(const entity_type & entity)
    {
        m_entities.push_back(entity);
    }

    void calculateNeighbors(const vector_type & position, flt32 radius)
    {
        flt32 rSq = radius*radius;
        m_neighbors.clear();

        std::for_each(m_entities.begin(), m_entities.end(), [&](entity_type ent){
            if(lengthSq(ent->getPosition() - position) <= rSq)
                m_neighbors.push_back(ent);
        });
    }

private:
    std::vector<entity_type> m_entities;
    std::list<entity_type> m_neighbors;
};

редактировать

вот код вокруг NeighborCalculator

//#1 
std::list<Vehicle *> vehicles;
vehicles.push_back(new Vehicle);
vehicles.push_back(new Vehicle);
vehicles.push_back(new Vehicle);

//#2 
NeighborCalculatorDummy<Vehicle *> neighborCalculator = new NeighborCalculatorDummy<Vehicle *>();

std::for_each(vehicles.begin(), vehicles.end(), [&](Vehicle * vehicle){
    neighborCalculator->addEntity(vehicle);
});

//#3 impl of addEntity
template <typename entity_type>
void NeighborCalculatorDummy<entity_type>::addEntity(const entity_type & entity)
{
    ...
    m_entities.push_back(entity);  //m_entities is - std::vector<Vehicle *> 
}

//#4 end of program
delete neighborCalculator;

std::for_each(vehicles.begin(), vehicles.end(), [&](Vehicle * vehicle){
    delete vehicle;
});

Ответы [ 3 ]

1 голос
/ 05 октября 2011

Мне кажется, что entity_type - это указатель (судя по лямбде for_each).

Вы, вероятно, хотели использовать

 NeighborCalculatorDummy<SomeEntity>

вместо

 NeighborCalculatorDummy<SomeEntity*>

в каком-то другом месте вашего кода (не показан)

Конечно, лямбда будет написана иначе:

[&](const entity_type& ent){
        if(lengthSq(ent.getPosition() - position) <= rSq)
            m_neighbors.push_back(ent);
    }

и, возможно, более похожие места, которые принимают тип entity_typeтребуется разыменование.

В качестве альтернативы вы можете использовать

  • vector<std::shared_ptr<entity_type> > вместо
  • Контейнеры повышения указателя

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

0 голосов
/ 18 февраля 2012

Я опустил виртуальный деструктор в родительском объекте Entity.Вот почему откат вызвал утечку.

0 голосов
/ 05 октября 2011

При таком определении, в зависимости от entity_type, код будет утекать или нет.

  • Если entity_type является указателем, деструктор по умолчанию просто вызовет деструктор вектора. Это освободит память, выделенную для этих указателей, но не вызовет удаление для них. Если этот класс «владеет» элементами внутри вектора и должен освободить их, вам необходимо добавить деструктор, который вызывает delete для всех элементов внутри вектора. В этом случае вы можете подумать о параметре шаблона, так как он не дает понять, что здесь нужен указатель.
  • Если entity_type является типом значения, деструктора по умолчанию достаточно, поскольку копии, помещенные в вектор, будут удалены деструктором вектора.
...