user12278897
user12278897

Reputation:

Memory leak with destructor in a class which has a nested class as private

I have a Tree class which has a nested private Node class. The constructor of my Tree class creates a Node object and set it to _info which is a pointer to a Node type in my Tree class.
I don't have any errors but when I check my program for memory leaks with valgrind, I see that I have memory leaks.
I know that the problem is with the deconstructor but i don't know how to solve it.
Just before showing the code, I should mention that the second argument of my template (N) is not important here and simply you could ignor it.


Here is my code: 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

main.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;
}

I am also open to any suggestion to improve my code.
Thank you in advanced

Upvotes: 0

Views: 165

Answers (1)

eerorika
eerorika

Reputation: 238461

_children = new Tree<T,N>[size]; 

There is no delete[] _children; anywhere.


Even more problematic:

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

This function returns a pointer to a solitary Tree* object that is not an element of an array.

return _info->getChildren()[index];

Here, you index into that pointer to a solitary object as if it were in an array. Using any other index than 0 has UB.

Upvotes: 1

Related Questions