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

Why do these visit methods cause memory leaks?

我正在开发一个使用访问者模式的中型 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++ 编程的新手,可能忽略了一些非常基本的问题。

copyCreator<nodeType>::push(ptr) 应该取得 ptr 的所有权。但如果 (a) ptr 不是 nodeType* 类型(由 dynamic_cast 确定),并且 (b) 没有 nodeType 类型的节点已经还没去过

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

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