I have the following code for creation of a node inside a graph. I'm getting resource leak error when I run a static checking tool (coverity). I would appreciate if you can point out how to improve the code:
class node {
public :
explicit node(std::string& name) : m_name(name) { }
void setlevel(int level)
{ m_level = level; }
private :
...
}
class graph {
public :
void populateGraph()
{
std::string nodeName = getNodeName();
/* I get error saying variable from new not freed or pointed-to in function
nc::node::node(const std::string...) */
node* NodePtr = new node(nodeName);
/* I get error saying variable NodePtr not freed or pointed-to in function
nc::node::setLevel(int) */
NodePtr->setLevel(-1);
if (m_name2NodeMap.find(nodeName) == m_name2NodeMap.end())
m_name2NodeMap[nodeName] = NodePtr;
NodePtr = NULL;
}
....
private :
std::map< std::string, node*> m_name2NodeMap;
}
I thought I needed to delete NodePtr
in populateGraph
, but then released it will call node desctructor (~node
) and delete the node from the graph. So, I set NodePtr=NULL
to see if it helps, but it is not.
I am not familiar with coverity or the exact rules that it uses, but it seems that you will have a memory leak if the name of the node is already in the map. That is, if the body of your if statement is not executed, then you loose the pointer to the memory that you just allocated. Perhaps you wanted something like:
if (m_name2NodeMap.find(nodeName) == m_name2NodeMap.end())
m_name2NodeMap[nodeName] = NodePtr;
else
delete NodePtr;
NodePtr = NULL;
Edit: since I responded almost at the same time as Daemin, let me add more details:
As ildjarn mentioned, you also need to deallocate those objects that do end up in the map by adding a destructor:
~graph()
{
for( std::map< std::string, node*>::iterator i = m_name2NodeMap.begin();
i != m_name2NodeMap.end(); ++i )
{
delete i->second;
}
}
For completeness, I should note that:
The preferred way to deal with complex object lifetimes is to use a smart pointer. For example, the boost::shared_ptr or the tr1::shared_ptr would work like this. Note: I may not have the syntax exact.
class node {
...
}
class graph {
public :
void populateGraph()
{
std::string nodeName = getNodeName();
boost::shared_ptr< node > NodePtr( new node(nodeName) );
NodePtr->setLevel(-1);
if (m_name2NodeMap.find(nodeName) == m_name2NodeMap.end())
m_name2NodeMap[nodeName] = NodePtr;
}
....
private :
std::map< std::string, boost::shared_ptr<node> > m_name2NodeMap;
}
};
See how we've eliminated the destructor and explicit calls to delete? Now the node objects will be destroyed automatically just like the node names.
On another node, you should look into the std::map::insert function which should eliminate that if statement all together.