尽管释放结构内存泄漏

memory leak despite freeing struct

我遇到了内存泄漏问题,我正在用 C 构建 BST 并且需要释放 BST。我的 BST_element:

typedef struct _BST_Node {
char* name;
char* public_key_file;
struct _BST_Node *left, *right;
} BST_Node;

我的分配函数:

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;

}

以及负责释放分配内存的函数:

void free_BST(BST_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);
}

我认为节点** 不是必需的,但这是一道考试题,所以我不能更改声明。

我的测试用例:

{
BST_Node* foo1 = new_BSTNode("hi","my");
BST_Node* foo2 = new_BSTNode("name","is");
foo1->left = foo2;
free_BST(&foo1);
}

根据 VS,内存泄漏是 foo1。但是在我的析构函数中,我明确地释放了这个结构?我该如何解决这个问题?

创建新节点时,不应将 leftright 指针设置为 NULL 以外的任何内容。

您不知道将需要哪些节点,因此总是分配是一种相当糟糕的形式,它会使事情变得混乱。

改为在树上插入时分配所需的子节点。

自由操作有几个问题

举个例子,假设 'current' 节点位于节点链的最末端,在右端。

那么条件就是:

currentNode->name != NULL
currentNode->public_key_file != NULL
currentNode->right = NULL
currentNode->left != NULL

free_BST() 函数中的第一行询问:

is the currentNode->right->name != NULL

然而,因为 currentNode->right 是 NULL,这将访问内存中的一些非常低的地址。与节点链无关的地址!

由于地址位于非常低的内存中,读取该地址很有可能会触发段错误事件。

对于代码的这个特殊问题,建议只查看

if( NULL != currentNode->right )
then 
    free name, 
    free public_key_file,         
    free currentNode

向左遍历节点时也有类似的问题

换句话说,不要访问当前节点以外的任何数据字段,因为 'other' 节点可能不存在