/************************* destroyBinTree this function destroys the binary tree and all data that is in the tree when destroy is called. ****************************/ void destroyBinTree(Tree * toDie) { if(toDie) { destroyBinTree(toDie->left); destroyBinTree(toDie->right); free(toDie); } }
void exploitMemLeaks() { // All data allocated and tracked, all will be freed int * low = calloc(1, sizeof(int)); * low = 1; int * mid = calloc(1, sizeof(int)); * mid = 2; int * hi = calloc(1, sizeof(int)); * hi = 3; printf("Created the following data to add to a tree:\n"); printf("Low: %d, Mid: %d, Hi: %d\n", * low, * mid, * hi); // Test inside a tree Tree * test = createBinTree(&compNum, &destructor); addToTree(test, mid); addToTree(test, low); addToTree(test, hi); printInOrder(test, &print); // Up to here, as long as destroyBinTree is called, no leaks are possible // Now lets look at some of the issues with the library // Left will contain Low (1), we know this. This function allocates memory // so it's return value must be freed Tree * left = getLeftSubtree(test); free(left); // All is well, no memory leaks here // Now let's get the right subtree, Hi (3), but before we free it, let's get // get one of it's subtrees too. We know it won't contain anything so // presumably we'll get some sort of error return value Tree * right = getRightSubtree(test); Tree * empty = getRightSubtree(right); if (empty == NULL) printf("The call to an empty subtree returned NULL.\n"); // Oh good, we did get some error handling, great now there's no problem // OOPS, no, there's a huge issue. The getSubtree functions are presumably // doing the following: allocating memory to a temporary new tree pointer, // checking what's in the subtree and returning NULL if nothing is in it. // So the temporary new tree pointer to allocated memory is completely lost // in all instances. // We can't even detect the error without a memory checker because the // following call of free(NULL) has no effect free(empty); free(right); destroyBinTree(test); }