简体   繁体   中英

C pointer being freed was not allocated

I made this BinaryTree implementation, which works fine except for the freeTree() method that says I am trying to free a pointer that wasn't allocated. I just cannot find where my logic is wrong here. I have no idea how to find exactly the pointer it at. Any tips, tricks?

#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>

struct BinaryTree
{
    int data;
struct BinaryTree *left;
struct BinaryTree *right;
};

typedef struct BinaryTree BinaryTree;

FILE *input;
FILE *output;

char dat[99];
int number;

BinaryTree tree;

void add(int data, BinaryTree *tree);
void inorderTraversal(BinaryTree *tree);
void freeTree(BinaryTree *tree);

int main()
{
input = fopen("/Users/sergeymikhaylyuk/Desktop/Program/Tree/input.txt", "r");
output = fopen("/Users/sergeymikhaylyuk/Desktop/Program/Tree/sorted.txt", "w");
while (fgets(dat, sizeof(dat), input))
{
    sscanf(dat, "%i", &number);
    add(number, &tree);
}
inorderTraversal(&tree);
freeTree(&tree);

}

void add(int data, BinaryTree *tree)
{
if (tree->data == 0)
{
    tree->data = data;
}
else
{
    if (tree->data < data && tree->right != NULL)
    {
        add(data, tree->right);
    }
    else if (tree->data < data)
    {
        tree->right = malloc(sizeof(BinaryTree));
        add(data, tree->right);
    }
    else if (tree->data > data && tree->left != NULL)
    {
        add(data, tree->left);
    }
    else if (tree->data > data)
    {
        tree->left = malloc(sizeof(BinaryTree));
        add(data, tree->left);
    }
}
}

void inorderTraversal(BinaryTree *tree)
{
if (tree != NULL)
{
    if (tree->left != NULL)
    {
        inorderTraversal(tree->left);
    }
    fprintf(output, "%i ", tree->data);
    if (tree->right != NULL)
    {
        inorderTraversal(tree->right);
    }
}

}
int i = 1;
void freeTree(BinaryTree *tree)
{
printf("%i ", i);
i++;
if (tree != NULL)
{
    if (tree->left != NULL)
    {
        freeTree(tree->left);
    }
    if (tree->right != NULL)
    {
        freeTree(tree->right);
    }
    free(tree);
}
}

The root node is on the stack because of this line

BinaryTree tree;

All other nodes are on the heap.

But you freeTree function free's all nodes including the root. Hence it gives the error trying to free a pointer which hasn't been malloced error .

The simplest fix is to change the above to

BinaryTree * ptree = malloc(sizeof(BinaryTree));
ptree->data = 0;
ptree->left = NULL;
ptree->right = NULL; 

and change all places where you are using &tree to ptree .

For eg.

add(number, &tree);

to

add(number, ptree);

Other than this, you also need to init left & right to NULL after you malloc at all places.

For eg. after

tree->right = malloc(sizeof(BinaryTree));

add

tree->right->data = 0;
tree->right->left = NULL;
tree->right->right = NULL;

When you allocate your nodes, you never initialize them before using them. The item returned by malloc() is not guaranteed to be initialized to zeros (or any other particular value). So you're left and right link pointers likely have garbage values. You should do something like this:

BinaryTree* alloc_node(void)
{
    BinaryTree* p = malloc(sizeof(BinaryTree));
    if (p) {
        p->data = 0;
        p->left = p->right = 0;
    }
    return p;
}

and call alloc_node() instead of malloc() to allocate a new node.

malloc returns newly allocated data but does not zero fill (initialize) the allocated structure. Therefore, if left and right are pointers, they point to a random, non-zero address. Consequently it appears is if you try to free data that you did not allocate.

A fix might look like this:


    ...
    tree->right = malloc(sizeof(BinaryTree));
    bzero(tree->right, sizeof(BinaryTree));
    add(data, tree->right);
    ...

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