【问题标题】:Memory leak with destructor in a class which has a nested class as private具有嵌套类作为私有的类中的析构函数的内存泄漏
【发布时间】:2019-11-07 16:40:08
【问题描述】:

我有一个 Tree 类,它有一个嵌套的私有 Node 类。我的 Tree 类的构造函数创建了一个 Node 对象并将其设置为 _info,它是我的 中的 Node 类型的指针>树类。
我没有任何错误,但是当我使用 valgrind 检查程序是否存在内存泄漏时,我发现我有内存泄漏。
我知道问题出在解构器上,但我不知道如何解决。
在展示代码之前,我应该提一下我的模板的第二个参数 (N) 在这里并不重要,您可以忽略它。


这是我的代码: tree.hpp


#ifndef TREE_HPP
#define TREE_HPP

#include <iostream>
#include <cstddef> 

template <typename T, char N>
class Tree {
private:
  class Node;
  Node* _info;
public:
  Tree();
  Tree(T, char);
  Tree(const Tree&) = delete;
  Tree& operator= (const Tree&) = delete;
  Tree (Tree&&);
  Tree& operator= (Tree&&);
  ~Tree() {delete _info;} // something is wrong here
  bool ins(char, Tree*);
  Tree* fils(char);
  void print(){
    std::cout << _info->getData() << std::endl;
  }
};

template <typename T, char N>
bool Tree<T, N>::ins(char index, Tree* childTree){
  if (_info){
    _info->getChildren()[index] = childTree;
    return true;
  }
  return false;
}

template <typename T, char N>
Tree<T, N>::Tree() 
  : _info(nullptr) {}

template <typename T, char N>
Tree<T, N>::Tree(T data, char size) {
  Node* node = new Node(data, size); // I think I don't free this
  _info = node;
}

template <typename T, char N>
Tree<T, N>::Tree(Tree&& t) {
  _info = t._info;
  t._info = nullptr;
}

template <typename T, char N>
Tree<T, N>& Tree<T, N>::operator= (Tree&& t) {
  if (&t != this) {delete _info; _info = t._info; t._info = nullptr;}
  return *this;
}

template <typename T, char N>
typename Tree<T,N>::Node* Tree<T, N>::info() { return _info;}

template <typename T, char N>
Tree<T,N>* Tree<T, N>::fils(char index){
  return _info->getChildren()[index];
}

template <typename T, char N>
class Tree<T, N>::Node {
private:
  T _data;
  Tree* _children;
  bool _isWord;
public:
  Node();
  Node(T, char);
  Tree** getChildren() {return &this->_children;}
  T getData(){return this->_data;}
  ~Node() = default;
};

template <typename T, char N>
Tree<T,N>::Node::Node(){
  _data = 0;
  _children = nullptr;
  _isWord = false;
}

template <typename T, char N>
Tree<T,N>::Node::Node(T data, char size){
  _data = data;
  _isWord = false;
  _children = new Tree<T,N>[size]; 
}

#endif

ma​​in.cpp

#include <iostream>
#include <cstddef>
#include <exception>
#include "tree.hpp"

#define SIZE 5
int main() {
  Tree<char,SIZE> n1('A',SIZE);
  Tree<char,SIZE> n1_1('B',SIZE);
  Tree<char,SIZE> n1_2('C',10); // ! here the size is always 5
  Tree<char,SIZE> n1_1_1('D',SIZE);
  n1.ins(0,&n1_1);
  n1.ins(1,&n1_2);
  n1_1.ins(0,&n1_1_1);
  n1.fils(0)->print();
  n1.fils(1)->print();  
  n1_1.fils(0)->print();
  return 0;
}

我也愿意接受任何改进我的代码的建议。
提前谢谢你

【问题讨论】:

  • 我也愿意接受任何改进我的代码的建议。 -- 不要用下划线开头你的变量名。
  • Node::~Node() 是默认的,不会删除 Node 拥有的指针
  • 我不知道Node中的默认析构函数是否会正确删除动态内存。如果你真正实现它,你可以保证你想要的行为,即触发删除树。
  • @sweenish 但如果我在 Node 类中执行~Node() {delete[] _children;},我会遇到分段错误。
  • Mohammadreza 不幸的是更接近正确。你需要弄清楚它为什么会出错并修复它。因为它不会崩溃而做错误的事情是解决问题的错误方法。您是否考虑过使用std::vector

标签: c++ class memory


【解决方案1】:
_children = new Tree<T,N>[size]; 

任何地方都没有delete[] _children;


还有更多问题:

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

此函数返回一个指向单独的Tree* 对象的指针,该对象不是数组的元素。

return _info->getChildren()[index];

在这里,您索引指向一个单独对象的指针,就好像它在一个数组中一样。使用 0 以外的任何其他索引都有 UB。

【讨论】:

  • 但是我不知道如何以其他方式编写此代码?我不能使用向量,我被数组卡住了
  • @Mohammadreza -- 好吧,你现在写它的方式有错误。您将得到的任何答案都将与此处的答案相似。所以我真的不知道你希望我们做什么。
  • 我想知道是否有人可以帮助我修复我在编码时犯的错误并将它们改进为更好的代码
猜你喜欢
  • 2015-08-28
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 2012-09-14
  • 2018-08-19
  • 1970-01-01
  • 1970-01-01
  • 2012-02-20
相关资源
最近更新 更多