简体   繁体   中英

Freeing TRIE structure in C recursively

I'm currently trying, to no avail, to successfully free a TRIE structure using a recursive function , but I'm seeing memory loss.

The trie structure is defined as:

typedef struct node
{
    bool is_word;
    struct node* children[27];
}
node;

and I have the following Node* declared globally:

node* trie = NULL;
node* root = NULL;

The second is used only to keep track of the root node and first one is receiving words from a file. To this point I was getting no errors when compiling my program without freeing the heap memory, other than memory loss.

After implementing an unload( ) function, I started coming across Segmentation Fault errors.

See a snippet of my code:

/*
Frees node by node recursively
*/

bool freeSpace(node* child)
{   
    for (int i = 0; i < 27; i++)
    {
        if(trie->children[i] != NULL)
        {
            freeSpace(trie->children[i]);
        }
    }
    free(trie);
    return true;
}

/**
 * Unloads dictionary from memory. Returns true if successful else false.
 */ 
bool unload()
{

    if(root != NULL)
    {
        trie = root;
        freeSpace(trie);

        if(freeSpace(trie))
            return true;
        else
            return false;
    }
    else
    {
        return false;
    }

}

Maybe my code is not very smart at the returning values and validation, but my main issue now is guaranteeing the recursion works as intended and no memory is leaking or segmentation fault is occurring. Any advices?

Thanks in advance!

Here is a modified version of your code snippet that makes more sense:

/*
Frees node by node recursively
*/

void freeSpace(node* t)
{   
    for (int i = 0; i < 27; i++)
    {
        if(t->children[i] != NULL)
        {
            freeSpace(t->children[i]);
        }
    }
    free(t);
}

/**
 * Unloads dictionary from memory. Returns true if successful else false.
 */ 
bool unload()
{

    if(root != NULL)
    {
        trie = root;
        freeSpace(trie);
        return true;
    }
    else
    {
        return false;
    }

}

The freeSpace function has been changed to use the parameter as the base of the trie to be freed. Your original version had an unused parameter child and used global variable trie instead, which didn't make sense.

There is no need for freeSpace to return a value as all it does is free stuff, and it was only returning a fixed value true . I changed its return type to void .

Your unload function was calling freeSpace twice on the same object, so I removed one of the calls.

I think your freeSpace() function should use child parameter instead of trie. This is how it should look like.

bool freeSpace(node* child){   
    for (int i = 0; i < 27; i++)
    {
        if(child->children[i] != NULL)
        {
            freeSpace(child->children[i]);
        }
    }
    free(child);
    return true;
}

Look closely at your code. Do you actually use the parameter to the function anywhere? You're actually always looking at the global trie pointer at each iteration, which isn't want you want to do.

To fix this, change your code so that you look at the node passed in as an argument and its children rather than the global trie pointer.

You have another issue to watch out for, and that's how you handle null pointers. Right now, you assume the argument pointer isn't null and then inspect each child to see whether it's non-null before recurring. But what if the trie itself is null to begin with? I'd consider creating a base case that checks if the trie is null and, if so, doesn't do anything. You can then eliminate the checks before the recursive calls you make and now properly guard against another edge case.

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