Reputation: 296
I'm having trouble with a memory leak, I am constructing a BST in C and need to free a BST. My BST_element:
typedef struct _BST_Node {
char* name;
char* public_key_file;
struct _BST_Node *left, *right;
} BST_Node;
My allocation function:
BST_Node* new_BSTNode(char* name, char* public_key_file) {
BST_Node* node = malloc(sizeof(BST_Node));
node->name = malloc((strlen(name) + 1) * sizeof(char));
node->public_key_file = malloc((strlen(public_key_file) + 1) * sizeof(char));
node->left = calloc(1,sizeof(BST_Node));
node->right = calloc(1,sizeof(BST_Node));
//check if allocation was correct
if (!node || !node->name || !node->public_key_file || !node->left || !node->right) {
printf(ALLOCATION_ERROR_MSG);
exit(ALLOCATION_ERROR);
}
//copy strings into struct
strcpy(node->name,name);
strcpy(node->public_key_file,public_key_file);
return node;
}
And the function responsible for freeing the allocated memory:
void free_BST(BST_Node** node) {
//free the children:
if(!((*node)->right->name==NULL))
free_BST(&((*node)->right));
else free((*node)->right);
if(!((*node)->left->name==NULL))
free_BST(&((*node)->left));
else free((*node)->left);
//free strings
free((*node)->public_key_file);
free((*node)->name);
free(*node);
}
I think the node** is not necessary, however this is an exam question so I'm not allowed to change the declaration.
My test case:
{
BST_Node* foo1 = new_BSTNode("hi","my");
BST_Node* foo2 = new_BSTNode("name","is");
foo1->left = foo2;
free_BST(&foo1);
}
The memory leak is foo1 according to VS. However in my destructor function, I explicitly free this struct? How can I solve this?
Upvotes: 2
Views: 212
Reputation: 16540
there are several problems with the free operation.
For an example, lets say the 'current' node is at the very end of the chain of nodes, on the right end.
Then the conditions would be:
currentNode->name != NULL
currentNode->public_key_file != NULL
currentNode->right = NULL
currentNode->left != NULL
The first line in the free_BST() function asks:
is the currentNode->right->name != NULL
however, because currentNode->right is NULL, this will be accessing some very low address in memory. An address that has nothing to do with the chain of nodes!
Due to the address being in very low memory, there is a good chance the reading of that address will trigger a seg fault event.
For this particular problem with the code, suggest only looking at
if( NULL != currentNode->right )
then
free name,
free public_key_file,
free currentNode
There is a similar problem when traversing left through the nodes
In other words, do not access data fields in anything other than the current node, as that 'other' node might not exist
Upvotes: 0
Reputation: 399881
You shouldn't set left
and right
pointers to anything but NULL
when creating a new node.
You don't know which nodes are going to be needed, so it's rather bad form to always allocate, and it makes things confusing.
Allocate the needed child node(s) when doing insert on the tree, instead.
Upvotes: 6