具有指针和嵌套节点的树结构中的内存泄漏 class

memory leak in a Tree structure with pointers and Node nested class

我有这个任务,我必须在其中定义一个树 class,它有一个嵌套的私有节点 class。
问题是我既不能使用 smart pointers 也不能使用 std::vector 也不能使用复制运算符和复制赋值。我只能使用原始指针。
所以我写了 class 并用 valgrind 测试它以检查我是否有内存泄漏,我做到了。我知道内存泄漏可能来自节点 class,因为我没有 free _children 但是当我这样做时,我遇到了分段错误。
我真的不知道如何解决这个问题。

在此先感谢您。

嗯,这不是清理代码,有很多内存泄漏的方法。 这是我认为您遇到问题的一个:

Tree() : _info(nullptr) {} 
...
~Tree() {
    delete _info;
  }

当然,还有更多地方可能出错:

Tree& operator= (Tree&& t) // check _info not null before calling delete _info

换句话说,您的 class Tree 有两个构造函数。一个接受类型 T 的值:Tree(T data)。这个构造器确实创建了一个 new 节点。这是您用来在 main() 函数中创建 Tree 的构造函数。

您还有另一个构造函数:默认构造函数。这是从 class Node 创建子节点时调用的构造函数:_children = new Tree<T,N>[N];

Tree() : _info(nullptr) 的默认构造函数不会创建新的 _info 节点。

当程序完成并调用析构函数时 - 尝试删除 nullptr

简单的解决方法是更改​​树析构函数:

~Tree() {
    if (_info) delete _info;
  }

Node::_children 是一个树数组,当你调用 getChildren 你 return 一个指针数组。所以调用 ins 可能会破坏内存。或者它可能会意外工作。

最好将 getChildren 更改为 return 对元素的引用,如下所示: Tree& getChildren(int index) { return _children[index]; }

或将 _children 的 def 更改为 Tree** _children; 初始化为 _children = new Tree<T,N>*[N];

T** getChildren() { return &this->children; }

returns children 成员的地址。稍后,您可以通过数组索引通过取消引用来使用该地址,方法是:

_info->getChildren()[index] = childTree;

这正在调用未定义的行为。要解决这个问题:

将您的成员更改为:

Tree** _children;

将您的 ctor 更改为:

Node(T data) 
    : _data( std::move(data) )
    , _children(new Tree<T,N>*[N]())
    , _isWord(false)
{
}

并注意指针语法的数组以及元素的值初始化,这将对数组进行零填充。

最后,将 getChildren() 成员更改为:

Tree** getChildren() { return this->_children; }

这应该会减轻你的 UB,同时也减轻你的错。不想粉饰这个。此处的手动内存管理容易出错且存在问题。至少使用智能指针会好得多,如果不是在有保证的情况下使用完全具体的对象的话。但就是这样。

备选

完全失去动态 children 分配。它的大小已经由 N 的编译时规范确定。所以用那个。

成员变得简单:

Tree* _children[N];

ctor 仍然可以通过这样做进行值初始化:

Node(T data) 
    : _data( std::move(data) )
    , _children()
    , _isWord(false)
{
}

并从析构函数中完全删除 delete [] children;