Question

My program involves combining tree lists in a queue, my program compiles perfectly and works for about half of the code then throws this error at me. I have narrowed it down to involving my freeTree and how i call it in encodefile, for some back story this is for an encoder that is based off of character frequencies in a textfile, so if there is a textfile with 5 different chars in it, then this code will start with 5 different nodes in the queue. Each initial node in the queue holds the char and the frequency, the priority queue is based off of frequencies, with a tiebreaker as the numeric value of the char.

malloc_printerr (action=3, str=0x7ffff7b98938 "double free or corruption (fasttop)", ptr=0x6034b0) at malloc.c:5027

This is what the structs look like, symbol stands for the char, and the weight is the frequency

struct treeNode
{
  unsigned char symbol;
  unsigned long weight;
  struct treeNode* left;
  struct treeNode* right;
  struct treeNode* next;
};

struct queue
{
  struct treeNode* first;
  struct treeNode* last;
};

This is my freeTree method

void freeTree( struct treeNode* root )
{
  if( root != NULL )
  {
    freeTree( root->left );
    freeTree( root->right );
    free( root );
  }
}

These are the variables or treeNodes i use in the main part of my code

  struct treeNode* newNode;
  struct treeNode* holder;

And this is where it is all being called that should be going through my queue combining two nodes into one tree with a node on top equal to the weight of both of the input nodes, and this should go on until the queue only contains one big tree

while( treeCount > 1 )
  {
    newNode = combineTwo( q->first, q->first->next );
    if( charCount == 2 )
    {
      holder = q->first;
      q->first = q->first->next;
      freeTree( holder );
      holder = q->first;
      q->first = newNode;
      freeTree( holder );
    }
    else
    {
      holder = q->first;
      q->first = q->first->next;
      freeTree( holder );
      holder = q->first;
      q->first = q->first->next;
      freeTree( holder );
      insertSortedNode( q, newNode );
    }
    charCount--;
    holder = NULL;
  }

And this is my combineTwo method, that will make the two input nodes into leaves on one node

struct treeNode* combineTwo( struct treeNode* first, struct treeNode* second )
{
  struct treeNode* newNode = createNode( '\0', (first -> weight) + (second -> weight));
  if( first -> weight > second -> weight )
  {
    newNode -> right = first;
    newNode -> left = second;
  }
  if( first -> weight < second -> weight )
  {
    newNode -> left = first;
    newNode -> right = second;
  }
  if( first -> weight == second -> weight )
  {
    if( first -> symbol > second -> symbol )
    {
      newNode -> right = first;
      newNode -> left = second;
    }
    if( first -> symbol < second -> symbol )
    {
      newNode -> left = first;
      newNode -> right = second;
    }
  }
  return newNode;
}

I will be here all day to answer any questions needed, if more info is needed

Was it helpful?

Solution

combineTwo makes a new node which (potentially) points newnode's left and right to the first and second parameter values. The code in your while loop then frees those pointers using freeTree.

For example:

newNode = combineTwo( q->first, q->first->next ); // newNode->left = q->first (possibly)
if( charCount == 2 )
{
  holder = q->first;
  q->first = q->first->next;
  freeTree( holder );      // freeing the original q->first here. newNode still points to it.

You need to work out whether the new node's left and right should point to the original tree nodes, or whether they (the original nodes) should be deleted. You can't do both without having invalid pointers.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top