【问题标题】:std::map causing memory leaks?std::map 导致内存泄漏?
【发布时间】:2011-12-04 16:24:21
【问题描述】:

编辑

为了让这篇文章更具建设性,并让它在未来可能对其他人有所帮助:

问题是这样的:

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


原问题:

我的应用程序出现内存泄漏,我不知道是什么原因造成的!我以为我正在释放我必须做的一切。奇怪的是:我每次运行应用程序时都没有内存泄漏。

简而言之,这就是我的应用所做的:

在初始化时,它会在 TileList 中创建 numRowsnumColumns new Tile()。 当鼠标悬停在屏幕上的某个位置并按住鼠标左键时,它会在 std::map 中添加 std::pair&lt;Point2, Prop*&gt; pp.second = new Prop()

有时我可以添加一大堆道具并退出应用程序而不会出现任何泄漏。有时我会添加和以前一样的道具,退出时会出现内存泄漏。

请帮忙。 以下是相关代码:

如果您需要查看我的代码的特定部分,只需对其进行评论,我将编辑问题

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);
    }
}

【问题讨论】:

  • 您是否尝试过在代码中使用valgrind 或其他 C/C++ 内存分析器?如果是这样,它告诉了你什么?
  • 一旦开始发现内存问题,就应该使用内存分析器,例如Valgrind
  • 好吧,我已将其添加到我的代码中:#if defined(DEBUG) |已定义(_DEBUG)_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); //_crtBreakAlloc= 44685; #endif 它告诉我这是“道具”资源。不过,我不知道怎么了
  • 我没有看到任何“新道具”,但您至少在两个地方删除了它们。一切都是为了匹配新闻和删除。
  • @Ashelly 这实际上是我的错误,我没有将那部分添加到代码中,它在简短的解释中。

标签: c++ memory-leaks std


【解决方案1】:

我认为你的问题可能出在这儿

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

在您的代码中,mProps 似乎拥有 Prop* 的所有权。但是如果添加了一个重复的 prop 就会泄漏,因为唯一的 Point2 只能存在 Prop 并且 ma​​p::insert 会失败并且 Prop 将被孤立。

每当您在地图或 stl 容器中插入指向对象的指针时。尝试将其更改为std::shared_ptr 以进行自动内存管理。在你的情况下,如果你这样做,你的析构函数都不需要做明确的清理,你根本不需要static PropRelease

【讨论】:

  • 当您插入到 std::map 时,如果映射中已经存在具有相同值的键,则插入将失败,所以这可能不是问题
  • @xcrypt 但是 OP 正在分配一个新的 Prop 并调用 PropAdd 并假设该属性将被地图删除。插入将失败,Prop 将被孤立
  • 对!你真是个天才!让我尝试解决这个问题:)
  • 最好的解决办法是使用 shared_ptr。至少要一个upvote :)
  • 我知道,但我现在故意避免使用 ptr-helpers,以便弄脏我的手并获得更多的内存管理经验。但是,是的,你是对的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-24
  • 2011-06-13
  • 2014-08-18
  • 2015-07-06
  • 2014-06-07
  • 2013-11-20
  • 2011-10-28
相关资源
最近更新 更多