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:
- 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?
- if insert fails that it doesn't clear your memory for you?
Some more specific information on the exact error report would be helpful.
精彩评论