std :: map вызывает утечки памяти? - PullRequest
2 голосов
/ 04 декабря 2011

EDIT

Чтобы сделать этот пост более конструктивным и, возможно, помочь другим в будущем:

Проблема была в следующем:

std::map<Point2, Prop*> mm;
std::pair<Point2, Prop*> p;

if(Keydown(VK_LBUTTON)) {
     p.first = pos; p.second = new Prop();
     mm.insert(p))
}

Таким образом, хотя карта итеративно перезаписывалась и освобождала все указатели Prop * в конце, были случаи, когда вставка не удалась (потому что пара с тем же ключом уже могла быть в дереве). Это означает, что новый объект Prop () станет осиротевшим.

Решения:

1) либо всегда используйте std :: shared_ptr (вероятно, лучшее решение)

2) или сделайте это:

std::map<Point2, Prop*> mm;
std::pair<Point2, Prop*> p;

if(Keydown(VK_LBUTTON)) {
     p.first = pos; p.second = new Prop();
     if(mm.insert(p).second == false) {
          delete p.second;
     }
}

Спасибо пользователю SO parapura rajkumar


Оригинальный вопрос:

У меня утечка памяти в приложении, и я не знаю, что их вызывает! Я думал, что освобождаю все, что мне нужно. Странная часть: у меня нет утечек памяти каждый раз, когда я запускаю свое приложение.

Короче говоря, вот что делает мое приложение:

При инициализации создает numRows раз numColumns new Tile() внутри TileList. Когда мышь находится в некоторой позиции на экране и удерживается левая кнопка мыши, она добавляет std::pair<Point2, Prop*> p с p.second = new Prop() к std::map.

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

Пожалуйста, помогите. Вот соответствующий код:

Если вам нужно увидеть определенную часть моего кода, просто закомментируйте его, и я отредактирую вопрос

PropList.h

class PropList
{
protected:
    std::map<Point2, Prop*> m_Props_m;

public:
    PropList(){}
    virtual ~PropList();

    bool PropAdd(std::pair<Point2, Prop*> p)
    {
        pair<map<Point2, Prop*>::iterator,bool> ret = m_Props_m.insert(p);
        return ret.second;
    }
    bool PropRemove( const Point2& pos );
    bool HasProp( const Point2& pos );

    void Tick();

protected:

};

static void PropRelease(const std::pair<Point2, Prop*>& p) {
    delete p.second;
}

PropList.cpp

PropList::~PropList()
{
    std::for_each(m_Props_m.begin(), m_Props_m.end(), &PropRelease);
}

bool PropList::PropRemove( const Point2& pos )
{
    std::map<Point2, Prop*>::iterator it = m_Props_m.find(pos);
    if (it == m_Props_m.end()) {
        return false;
    }
    delete (*it).second;
    m_Props_m.erase(it);
    return true;
}

TileList.h

class TileList
{
protected:
    std::vector<std::vector<Tile*> > m_Tiles_v;
    PropList m_PropList;

    UINT m_iRowNum;
    UINT m_iColNum;

public:
    TileList(UINT numColumns, UINT numRows);
    virtual ~TileList();

    //Props
    void PropAdd(std::pair<Point2, Prop*> p);
    void PropRemove(const Point2& pos);
    bool HasProp(const Point2& pos);
    void Tick();

    UINT GetNumRows(){return m_iRowNum;}
    UINT GetNumCols(){return m_iColNum;}

protected:
};

TileList.cpp

TileList::TileList(UINT numColumns, UINT numRows)
    :m_iRowNum(numRows)
    ,m_iColNum(numColumns)
{
    for (UINT i = 0; i < numRows; ++i) {
        m_Tiles_v.push_back(std::vector<Tile*>());
        for (UINT j = 0; j < numColumns; ++j) {
            m_Tiles_v[i].push_back(new Tile());
        }
    }
}

TileList::~TileList()
{
    BOOST_FOREACH(std::vector<Tile*> col_tiles_v, m_Tiles_v)
    {
        BOOST_FOREACH(Tile* pTile, col_tiles_v)
        {
            delete pTile;
        }
    }
}

void TileList::PropAdd(std::pair<Point2, Prop*> p)
{
    if(m_PropList.PropAdd(p)) {
        m_Tiles_v[p.first.y][p.first.x]->setOccupied(true);
    }
}

void TileList::PropRemove(const Point2& pos) 
{
    if(m_PropList.PropRemove(pos)) {
        m_Tiles_v[pos.y][pos.x]->setOccupied(false);
    }
}

1 Ответ

6 голосов
/ 04 декабря 2011

Я думаю, что ваша проблема может лежать здесь

 bool PropAdd(std::pair<Point2, Prop*> p)
    {
        pair<map<Point2, Prop*>::iterator,bool> ret = m_Props_m.insert(p);
        return ret.second;
    }

Кажется, что в вашем коде mProps владеет Prop *.Но если к нему добавится повторяющийся реквизит, это приведет к утечке, поскольку для уникального Point2 может существовать только Prop , а map :: insert завершится ошибкой и Опора будет осиротевшей.

Всякий раз, когда вы вставляете указатели на объект в карте или контейнере stl.Попробуйте изменить его на std::shared_ptr для автоматического управления памятью.В вашем случае, если вы сделаете это, оба ваших деструктора не должны делать явную очистку и вам вообще не понадобится static PropRelease

...