为什么这些访问方法会导致内存泄漏?

时间:2017-07-24 20:48:39

标签: c++ c++11 memory-leaks visitor-pattern

我正在研究一个使用访问者模式的中型C ++框架。

对实现此框架的程序的valgrind测试报告了一些内存泄漏,可以追踪到其中一个访问者,即copyCreator

template<typename copyNodeType>
struct copyCreator {
    copyCreator {}
    copyCreator(node * firstVisit) {
        firstVisit->accept(*this);
    }

    ~copyCreator() {
        copy.reset();
        for(auto ptr : openList) {
            delete ptr;
        }
    }

    std::unique_ptr<copyNodeType> copy = 0;
    vector<nonterminalNode *> openList;

    // push to tree
    template<typename nodeType>
    void push(nodeType * ptr) {
        if (copy) {
            // if root is set, append to tree
            openList.back()->add_child(ptr);
        }
        else {
            auto temp = dynamic_cast<copyNodeType *>(ptr);
            if(temp) {
                copy = std::unique_ptr<copyNodeType>(temp);
            }
        }
    }

// ...

    void visit(struct someNonterminalNode & nod) {
    auto next = new someNonterminalNode(); //This is leaked
    push(next);
    openList.push_back(next);
    nod.child->accept(*this);
    openList.pop_back();
};

有两个主要原因让我对此感到困惑:

  • 两个不同的构造函数会导致不同数量的泄漏
  • 据报道,在访问期间发生泄漏

所有节点的accept方法只会触发对正确访问者的visit方法的标准双重调度。

我是C ++编程的新手,可能忽略了一些非常基本的问题。

1 个答案:

答案 0 :(得分:2)

copyCreator<nodeType>::push(ptr)应该取得ptr的所有权。但是,如果(a)ptr不是nodeType*类型(由dynamic_cast确定),并且(b)类型nodeType没有类型的节点,则它无法执行此操作访问了。

换句话说,copyCreator<nodeType>创建并迅速泄漏所有节点的副本,直到遇到nodeType类型的节点。

这正是copyCreator<programNode> cpy2(&globalScope, a);中发生的情况,其中aforallNode*cpy2期望遇到programNode(它从未做过),同时,它会复制并泄漏所有其他节点。