Search code examples
cbinary-search-treefree

Pointer not NULL even after assigning it to NULL (C)


I'm attempting to free two Binary Search Trees (BST). While both BSTs maintain their own nodes, the objects they include are the same as I'm told to maintain two BSTs in different sorted orders. This leads to a double free situation as when I free the second BST, the object is still there. I thought to set the pointer to NULL after, as freeing a null pointer is safe. But according to my breakpoints, the pointers are not NULL entering the second free call.

Here's the function where I'm attempting to free both sets of BSTs.

void freeEmpDatabase(EmpDatabase database) {
    freeTree(database.info->ssn_top);
    freeTree(database.info->id_top);
    free(database.info);
}

Here's the function where I'm freeing an individual tree.

void freeTree(BinaryTree * tree) {
    if (tree != NULL) {
        freeTree(tree->right);
        free(tree->Object);
        freeTree(tree->left);
        tree->Object = NULL;
        free(tree);
    }
}

Here are the relevant structs. (This is a prelab assignment that made me pass by value the "Database" struct, hence the EmpInfo pointer).

typedef struct BinaryTree {
    void * Object;
    struct BinaryTree * left;
    struct BinaryTree * right;
}BinaryTree;
typedef struct EmpInfo {
    BinaryTree * ssn_top;
    BinaryTree * id_top;
    int size;
    int error;
}EmpInfo;
typedef struct EmpDatabase {
    EmpInfo * info;
}EmpDatabase;

I'd appreciate any help possible. Thank you.


Solution

  • As @Yunnosch explains, despite them both pointing to the same Object, the pointers themselves are copies. To remedy my specific usecase, I just added a boolean value to control whether or not I need to free the Object pointer:

    void freeEmpDatabase(EmpDatabase database) {
        freeTree(database.info->ssn_top, 1);
        freeTree(database.info->id_top, 0);
        free(database.info);
    }
    
    void freeTree(BinaryTree * tree, int freedObject) {
        if (tree != NULL) {
            freeTree(tree->right, freedObject);
            if (freedObject == 1) {
                free(tree->Object);
            }
            freeTree(tree->left, freedObject);
            tree->Object = NULL;
            free(tree);
        }
    }