C 什么时候应该释放动态分配的内存?

C 什么时候应该释放动态分配的内存?,c,memory,dynamic,calloc,C,Memory,Dynamic,Calloc,本质上,我创建了一段由树组成的代码,其中每个树节点都有自己的包含数据的链表(每个树节点也包含数据)。因此,每个树节点可以有多个数据项用于该特定树节点 因此,为了创建这个结构,我调用一个treenode,将该treenode的地址传递给createListNode函数,然后调用一个ListNode。我的困惑其实源于,我到底应该在哪里释放记忆?仅在程序结束时返回0;大体上,或者其他地方。记住,一旦所有输入都添加到树和列表中,它就会要求用户输入一个名称,并显示适合该名称的数据链接列表 干杯 T.C 编

本质上,我创建了一段由树组成的代码,其中每个树节点都有自己的包含数据的链表(每个树节点也包含数据)。因此,每个树节点可以有多个数据项用于该特定树节点

因此,为了创建这个结构,我调用一个treenode,将该treenode的地址传递给createListNode函数,然后调用一个ListNode。我的困惑其实源于,我到底应该在哪里释放记忆?仅在程序结束时返回0;大体上,或者其他地方。记住,一旦所有输入都添加到树和列表中,它就会要求用户输入一个名称,并显示适合该名称的数据链接列表

干杯

T.C

编辑:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

typedef struct ListNode {
    char            *number;
    struct ListNode *next;
}ListNode;

typedef struct TreeNode {
    char            *name;
    ListNode        *numbers;
    struct TreeNode *left;
    struct TreeNode *right;
}TreeNode;

TreeNode* AddNode(TreeNode *, char *, char *);
void  AddNum(TreeNode *, char *);
void N_Print(TreeNode* root);
TreeNode* SearchTree(TreeNode* root, char *search);

int main(void) {
char my_string[50], name[25], number[25];
TreeNode *root = NULL;
while ((fgets(my_string, 50, stdin)) != NULL) {
        if (my_string[0] == '.')
            break;      
    sscanf(my_string, "%s %s", name, number); 
    root = AddNode(root, name, number);  
}   
N_Print(root);
free(root);
free(root->numbers);
return 0;
}

TreeNode* AddNode(TreeNode *root, char *name, char *number) {
int comparison;   
if (root == NULL) {
    root = (TreeNode*)calloc(1,sizeof(TreeNode));
    root->name = strdup(name); 
    root->left = root->right = NULL;      
    AddNum(root, number);
}else if ((comparison = strcasecmp(name, root->name)) < 0)
    root->left = AddNode(root->left, name, number);
else if ((comparison = strcasecmp(name, root->name)) > 0) {
    root->right = AddNode(root->right, name, number);
} else if ((comparison = strcasecmp(name, root->name)) == 0 ) {
    AddNum(root, number);
}       
return root;
}

void AddNum(TreeNode *tn, char *number) {
 ListNode *ln = (ListNode *)calloc(1, sizeof(ListNode));
 ln->number = strdup(number);
 ln->next = tn->numbers;
 tn->numbers = ln;
}

TreeNode* SearchTree(TreeNode* root, char *search) {
int comparison;
if (root == NULL) {
    return NULL;
} else if ((comparison = strcasecmp(search, root->name)) == 0) {
    return root;
} else if ((comparison = strcasecmp(search, root->name)) < 0) {
     return SearchTree(root->left, search);
} else if ((comparison = strcasecmp(search, root->name)) > 0) 
     return SearchTree(root->right, search);    
}

void N_Print(TreeNode* root) {
TreeNode* search_val;
char search[25];
while(1) {
    printf("Type a name please: ");
    scanf("%24s", search);
            if (search[0] == '.')
                    break;
    search_val = SearchTree(root, search); 
    if (search_val == NULL) {
        printf("NOT FOUND\n");
        continue;
    }
    ListNode* ln = search_val->numbers;
    while ( ln != NULL) {
            printf("%s\n", ln->number);
            ln = ln->next;
    }
}
}
#包括
#包括
#包括
#包括
类型定义结构列表节点{
字符*数字;
结构ListNode*next;
}列表节点;
类型定义结构树节点{
字符*名称;
列表节点*编号;
结构树节点*左;
结构树节点*右侧;
}三烯醇;
树节点*添加节点(树节点*,字符*,字符*);
void AddNum(TreeNode*,char*);
无效N_打印(TreeNode*根);
TreeNode*搜索树(TreeNode*根,字符*搜索);
内部主(空){
字符my_字符串[50],名称[25],数字[25];
TreeNode*root=NULL;
while((fgets(my_string,50,stdin))!=NULL){
如果(我的_字符串[0]='.'))
打破
sscanf(我的字符串,“%s%s”,名称,编号);
root=AddNode(根、名称、编号);
}   
N_打印(根);
自由根;
自由(根->数字);
返回0;
}
TreeNode*AddNode(TreeNode*根,字符*名称,字符*编号){
整数比较;
if(root==NULL){
root=(TreeNode*)calloc(1,sizeof(TreeNode));
root->name=strdup(名称);
根->左=根->右=空;
AddNum(根,数字);
}如果((比较=strcasecmp(名称,根->名称))<0,则为else
根->左=添加节点(根->左,名称,编号);
如果((比较=strcasecmp(名称,根->名称))>0,则为else{
根->右=添加节点(根->右,名称,编号);
}else if((比较=strcasecmp(名称,根->名称))==0){
AddNum(根,数字);
}       
返回根;
}
void AddNum(树节点*tn,字符*number){
ListNode*ln=(ListNode*)calloc(1,sizeof(ListNode));
项次->编号=strdup(编号);
ln->next=tn->编号;
tn->number=ln;
}
TreeNode*搜索树(TreeNode*根,字符*搜索){
整数比较;
if(root==NULL){
返回NULL;
}else if((比较=strcasecmp(搜索,根->名称))==0){
返回根;
}如果((比较=strcasecmp(搜索,根->名称))<0,则为else{
返回搜索树(根->左,搜索);
}如果((比较=strcasecmp(搜索,根->名称))>0,则为else
返回SearchTree(根->右,搜索);
}
无效N_打印(树节点*根){
TreeNode*搜索值;
字符搜索[25];
而(1){
printf(“请键入名称:”);
scanf(“%24s”,搜索);
如果(搜索[0]='。)
打破
search_val=SearchTree(根,搜索);
if(search_val==NULL){
printf(“未找到”);
继续;
}
ListNode*ln=搜索值->数字;
while(ln!=NULL){
printf(“%s\n”,项次->编号);
ln=ln->next;
}
}
}
最佳计划(IMO)是在不再需要访问的位置释放内存。但是,如果您只使用少量动态分配的内存,那么如果您在程序结束时完成所有操作(假设您跟踪所有操作),则可能不会产生太大影响。

很简单:


当你不再需要时,你可以释放内存。在您的情况下,似乎永远都不需要删除节点,因此不必担心删除任何节点。当程序退出时,它会自动释放。但要小心,应该删除所有引用它的指针超出范围的内存,使其无法使用。这可能会导致内存泄漏。

当您不再需要从免费存储中获取的资源时。因此,这取决于您不使用calloc资源的点,您可以启动免费it。但是要小心悬空引用。

当不再需要时,应该释放内存。这当然取决于应用程序的需要


在垃圾收集环境(例如Java)中,当没有任何东西指向垃圾收集器时,垃圾收集器会释放内存。从这一点开始,您需要确保在删除对内存的引用之前释放内存。

您可以在不再需要它时释放所有数据,就像打印完数据一样。在您的情况下,如果这就是您的程序所做的一切,那么它实际上并不重要,因为内核将在终止时释放程序分配的所有内存。但是,如果程序继续运行,这很重要,因为这意味着您占用了无法用于其他程序的内存


这有点像以前版本的firefox,在关闭一个标签后没有释放内存。程序一直在请求越来越多的内存,但没有释放它。

一旦不再使用内存,就释放内存。如果在程序退出之前发生这种情况,那么在返回之前释放内存。如果程序想继续执行任何操作,而您不再需要该树,请释放它并继续执行程序


例如,如果树中的链接列表在某个阶段会缩小,则应立即释放不再使用的节点。

正如上面所有人所说,在不再需要时释放它,但另外,尝试在创建的同一级别上释放通常是一个好主意。这在传递引用时更为复杂。

基本上,我已经创建了一段代码。酷。有机会展示这篇文章吗?太好了,现在你的问题被源代码修饰了,这使它更清楚了(当然,至少对那些知道如何阅读C源代码的人来说是这样)。