对象创建期间资源泄漏

我有以下代码用于在图形内创建节点。当我运行静态检查工具(覆盖率)时,我遇到了资源泄漏错误。如果您能指出如何改进代码,我将不胜感激:
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;   
}
我以为我需要
delete NodePtr
populateGraph
,但随后发布它会调用node desctructor(
~node
)并从图中删除该节点。所以,我设置
NodePtr=NULL
看它是否有帮助,但事实并非如此。     
已邀请:
我不熟悉它所使用的覆盖率或确切规则,但如果节点的名称已经在地图中,您似乎会有内存泄漏。也就是说,如果你的if语句的主体没有被执行,那么你就会松开指向你刚刚分配的内存的指针。也许你想要的东西:
if (m_name2NodeMap.find(nodeName) == m_name2NodeMap.end())  
    m_name2NodeMap[nodeName] = NodePtr;  
else
    delete NodePtr;
NodePtr = NULL; 
编辑:由于我几乎与Daemin同时回复,让我添加更多细节: 正如ildjarn所提到的,你还需要通过添加析构函数来解除分配在地图中最终的对象:
~graph()
{
    for( std::map< std::string, node*>::iterator i = m_name2NodeMap.begin(); 
         i != m_name2NodeMap.end(); ++i )
    {
        delete i->second;
    }
}
为了完整起见,我应该注意: 析构函数完成后,地图将自动删除,因为它是一个成员变量。 删除地图时,将自动删除节点映射中的条目。 删除条目时将删除字符串键。 处理复杂对象生命周期的首选方法是使用智能指针。例如,boost :: shared_ptr或tr1 :: shared_ptr就像这样工作。注意:我的语法可能不完整。
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;   
    }
};
看看我们如何消除析构函数和显式删除调用?现在节点对象将像节点名一样自动销毁。 在另一个节点上,你应该查看std :: map :: insert函数,它应该将if语句全部消除在一起。     
你需要做的是给
graph
一个析构函数并在其中,
delete
m_name2NodeMap
中的所有
node*
s。当然,因为你需要一个析构函数,你还需要一个复制构造函数和一个复制赋值运算符,否则你肯定会得到内存损坏。 对于
if (m_name2NodeMap.find(nodeName) == m_name2NodeMap.end())
delete NodePtr;
,你还需要一个
else
条款。     
当你不将它添加到列表中时,你不会释放
NodePtr
if
声明需要你所在的其他地方
if (m_name2NodeMap.find(nodeName) == m_name2NodeMap.end())
{
    m_name2NodeMap[nodeName] = NodePtr;
}
else
{
    delete NodePtr;
}
NodePtr = NULL;
    
其他人已经涵盖了泄漏的问题。事实上有很多泄漏,所以我甚至都不会对它们进行评论...(至少
populateGraph
~Graph
Graph(Graph const&)
Graph& operator=(Graph const&)
......) 我更愿意提供一个有效的简单解决方案:
class Graph
{
public:
  void addNode(std::string name) {
    _nodes.insert(std::make_pair(name, Node(name));
  }

private:
  std::map<std::string, Node> _nodes;
};
这里发生了什么 ? 动态内存分配是不必要的,
map
可以完美地包含
Node
的值,并且你不会以这种方式泄漏。
std::map::insert
只会在没有等效键的情况下执行插入,不需要执行
find
+
[]
(因为计算存储元素的位置的两倍,这是复杂的两倍)     

要回复问题请先登录注册