1
votes

I'm new to valgrind and I ran it with some code I wrote for a quadtree.

I've written a function that recursively frees the Nodes from the quadtree:

void destroyTree (Node* p)
{
    if (!p) return;

    for (size_t i = 0; i < 4; ++i)
        destroyTree(p->child[i]);

    free(p);
}

I call that function in the main function:

int main( int argc, char **argv ) {

  Node *head;

  // make the head node
  head = makeNode( 0.0,0.0, 0 );

  // make a tree
  makeChildren( head );
  makeChildren( head->child[0] );
  makeChildren( head->child[1] );
  makeChildren( head->child[2] );
  makeChildren( head->child[3] );

  // print the tree for Gnuplot
    writeTree( head );
  return 0;

  //destroy tree
  destroyTree (head);
  return 0;
}

When I run valgrind its showing that I lose some memory.

The structure is:

struct qnode {
  int level;
  double xy[2];
  struct qnode *child[4];
};
typedef struct qnode Node;

I call malloc in buildTree:

Node *makeNode( double x, double y, int level ) {

  int i;

  Node *node = (Node *)malloc(sizeof(Node));

  node->level = level;

  node->xy[0] = x;
  node->xy[1] = y;

  for( i=0;i<4;++i )
    node->child[i] = NULL;

  return node;
}

How do I stop the leak? Is there something wrong with my freeing function or is it somewhere else?

valgrind memory leak

1
It says a malloc call in makenode is unfreed. You should share that function.StoryTeller - Unslander Monica
@StoryTeller I've added the code where I use malloc aboveanon2000
you're using return 0 in the middle of your code so destroy function isn't called!! please enable warningsJean-François Fabre
In makenode, you have a member variable called xy that appears to be either an array or pointer. How are you allocating space for that, and likewise, how are you freeing it? Before you free a node, you also have to free any pointers inside of it, first.Alex Reynolds
@Jean-FrançoisFabre I tried removing the return 0 but that didn't make a differenceanon2000

1 Answers

1
votes

okay, since noone spotted this, the end of main reads:

  // print the tree for Gnuplot
    writeTree( head );
  return 0;    // <----------- wooooot!

  //destroy tree
  destroyTree (head);
  return 0;
}

We notice that the 2 last lines are unreacheable because there's a return 0 statement just above this. So the destroyTree method is never called, which explains the memory leak.

Always enable compiler warnings and read them. The control flow is simple enough, every compiler detects dead code here.

That said, even -Wall -Wextra doesn't work here, the -Wunreachable-code flag must be added explicitly (Why does GCC not warn for unreachable code?)