简体   繁体   中英

Freeing a tree in C

So I've been given the structure of a tree where each node has up to 2 children:

typedef struct one_node_t one_node_t;

typedef struct two_nodes_t two_nodes_t;

typedef struct my_tree_t {
  int numberOfNodes; //== 1 || numberOfNodes == 2

   // If the node is a leaf, it is represented by (*oneNode==NULL && numberOfNodes == 1)
    union {
       one_node_t* one;
       two_nodes_t* two;
    } nodeC;
} my_tree_t;

struct one_node_t {
  one_node_t* child;
};

struct two_node_t {
  my_tree_t children[2];
};

Now I was trying to write a function void freeMyTree(my_tree_t* myTree) which should free the allocated space of the tree myTree is pointing towards:

void freeMyTree(my_tree_t* myTree) {
  if(myTree->numberOfNodes == 2){
      freeMyTree(myTree->nodeC.two->children);
      freeMyTree(&myTree->nodeC.two->children[1]);
      free(myTree->nodeC.two);
      myTree->nodeC.two = NULL;
  }else{
      if(myTree->nodeC.one->child != NULL)
          freeMyTree(myTree->nodeC.one->child);
      free(myTree->nodeC.one);
      myTree->nodeC.one = NULL;
  }
}

But it seems like no space is freed. I guess there has to be some kind of misunderstanding of myself how to free up space, but googling didn't help me to understand it.

I think that space is not freed up because I create my files using gcc with the -fsanitize=leak option.

If I created a my_tree_t* a = calloc(1, sizeof(my_tree_t)) earlier the leak sanitizer tells me if I did not free it. However after calling freeMyTree(a) it will still tell me the same thing.

Edit: The error messages explcitly says that a one/two was not freed. Because they are point to lines like:

my_tree_t t;
t.nodeC.two = calloc(1, sizeof(two_nodes_t)); //<== POINTING TO THIS LINE

All the free() s that you do are free(myTree->nodeC.one); and free(myTree->nodeC.two); but nowhere do I see you doing the following: free(myTree->nodeC.one->child);

This is not a tree where each node has up to 2 children. This is a tree where each node has either exactly two children, or no children at all and an associated base 1 natural number. Indeed,

struct one_node_t {
   one_node_t* child;
};

contains no subtrees. It is a linked list with no information in the nodes. The only information that such a list carries is its length. So this is an inefficient representation of some natural number. (We ignore the possibility of a looped linked list).

The correct way to free such list would be something like

one = myTree->one;
while (one) {
  tmp = one->child;
  free(one);
  one = tmp;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM