我需要执行此任务,其中必须定义一个具有嵌套的私有Node类的Tree类。
问题是我既不能使用smart pointers
也不能使用std::vector
,也不能使用复制运算符和复制分配。我只允许使用原始指针。
因此,我编写了该类,并使用 valgrind 进行了测试,以检查是否存在内存泄漏,并且确实如此。我知道内存泄漏可能是由于Node类引起的,因为我不是free
_children
,但是当我这样做时,会遇到分段错误。
我真的不知道该如何解决这个问题。
非常感谢您。
我需要执行此任务,其中必须定义一个具有嵌套的私有Node类的Tree类。
问题是我既不能使用smart pointers
也不能使用std::vector
,也不能使用复制运算符和复制分配。我只允许使用原始指针。
因此,我编写了该类,并使用 valgrind 进行了测试,以检查是否存在内存泄漏,并且确实如此。我知道内存泄漏可能是由于Node类引起的,因为我不是free
_children
,但是当我这样做时,会遇到分段错误。
我真的不知道该如何解决这个问题。
非常感谢您。
T** getChildren() { return &this->children; }
返回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;
;
好吧,这不是带有大量内存泄漏方法的清理代码。 我认为这是您遇到的一个问题:
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
节点。这是用于在Tree
函数中创建main()
的构造函数。
您有另一个构造函数:默认构造函数。这是从class Node
:_children = new Tree<T,N>[N];
此默认构造器Tree() : _info(nullptr)
不会创建新的_info
节点。
程序结束并且调用了析构函数后-试图删除nullptr
。
简单的解决方法是更改Tree析构函数:
~Tree() {
if (_info) delete _info;
}
您Node::_children
是一个Trees数组,当您调用getChildren
时,您将返回一个指针数组。因此,调用ins
可能会破坏内存。否则可能会偶然起作用。
最好将getChildren
更改为将引用返回给elemet,方法是:
Tree& getChildren(int index) { return _children[index]; }
或将_children
的def更改为Tree** _children;
初始化为_children = new Tree<T,N>*[N];