开发者

Assertion trying to delete an empty object

trying to solve a mem leak I've changed this:

void addListener(IListener* listener, const std::string& appender )
{
     std::pair<t_ListenerVectorMap::iterator,bool> p =
    listenerVectorMap.insert(std::string(appender), new t_ListenerVector);
    p.first->second->push_back(listener);

    //add the appender
    addAppender(appender);
}

By t开发者_StackOverflowhis:

void addListener( IListener* listener,const std::string& appender )
{
    t_ListenerVector* lv = new t_ListenerVector;
    std::pair<t_ListenerVectorMap::iterator,bool> p =
    listenerVectorMap.insert(std::string(appender), lv);

    p.first->second->push_back(listener);
    if (!p.second)
    {
        delete lv;
    }

    addAppender(appender);
}

The leak I'm trying to get ride is the new t_ListenerVector (is a boost::ptr_vector). When appender already exists into listenerVectorMap, then insert operation doesn't not modify contents of map, so new t_ListenerVector isn't inserted and becomes a mem leak.

The change is to avoid this leak. If no new insertion as been done, lv is not inserted so I do remove it. But the problem is that delete lv throws an assertion (in vc\include\vector Line:70). If lv hasn't been changed, why this error?

Some ideas are welcome. Thanks


do the check to see if it exists in the map first, then call new to create the object. This isn't necessarily the source of the bug, but it's a more efficient practice.


For this answer I am assuming that the type of t_ListenerVectorMap is boost::ptr_map<std::string, boost::ptr_vector<IListener>>. If it isn't then this answer is probably worthless.


You have a misunderstanding about how boost::ptr_map works. It is true that your original code contains a memory leak, but your replacement code is even worse. listenerVectorMap.insert(std::string(appender), lv) makes listenerVectorMap take ownership of lv, regardless of whether lv is inserted or not. This means that the delete lv; line results in a double-deletion.

To fix the memory leak in the first version of your code, all you have to do is this:

void addListener(IListener* listener, const std::string& appender )
{
    std::auto_ptr<IListener> ls(listener);
    //The original code leaked here if the std::string constructor threw.
    std::pair<t_ListenerVectorMap::iterator,bool> p =
        listenerVectorMap.insert(appender, new t_ListenerVector());
    p.first->second->push_back(ls);

    //add the appender
    addAppender(appender);
}


If the assertion is coming from your call to delete I would check to make sure that:

  1. lv is properly initialised. Maybe it's got a floating pointer interally which by calling delete calls it's destructor and makes it try to free a random bit of memory?
  2. if insert fails that it doesn't clear your memory for you?

Some more specific information on the exact error report would be helpful.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜