Когда следует освобождать динамически выделенную память?

По сути, я создал фрагмент кода, состоящий из дерева, в котором каждый узел дерева имеет свой собственный связанный список, содержащий данные (каждый узел дерева также содержит данные). Таким образом, каждый узел дерева может иметь несколько элементов данных для этого конкретного узла дерева.

Поэтому для создания этой структуры я вызываю узел дерева, передаю адрес этого узла дерева функции createListNode и вызываю узел списка. Мое замешательство действительно связано с тем, где именно я должен освобождать память? Просто в конце программы перед возвратом 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;
    }
}
}

person PnP    schedule 28.11.2011    source источник
comment
Essentially, I have created a piece of Code. Прохладно. Есть ли шанс показать это произведение?   -  person Darin Dimitrov    schedule 29.11.2011
comment
Отлично, теперь ваш вопрос дополнен исходным кодом, что делает его более понятным (ну, по крайней мере, для людей, умеющих читать исходный код C, конечно).   -  person Darin Dimitrov    schedule 29.11.2011


Ответы (7)


Вы должны освободить память, когда она больше не нужна. Это, конечно, зависит от потребностей вашего приложения.

В средах со сборкой мусора (например, Java) сборщик мусора освобождает память, когда на нее ничего не указывает. Следуя этому в качестве отправной точки, вы должны обязательно освободить память, прежде чем удалять ссылки на нее.

person David V    schedule 28.11.2011

Лучший план (ИМО) — освободить память в том месте, где вам больше не нужен доступ к ней. однако, если вы используете только небольшой объем динамически выделяемой памяти, это, вероятно, не будет иметь большого значения, если вы сделаете все это в конце своей программы (при условии, что вы все это отслеживаете)

person smitec    schedule 28.11.2011

Это просто:

Вы освобождаете память, когда она вам больше не нужна. В вашем случае кажется, что вам никогда не придется удалять узел, поэтому не беспокойтесь об удалении. Он автоматически освобождается при выходе из вашей программы. Однако будьте осторожны, вы должны удалить всю память, все ее указатели, ссылающиеся на нее, выходят за пределы области действия, что делает ее непригодной для использования. Это может вызвать утечку памяти.

person slartibartfast    schedule 28.11.2011

Когда вам больше не нужны ресурсы, полученные из бесплатного магазина. Таким образом, в зависимости от того, в какой момент вы не используете ресурсы calloc, вы можете начать освобождать их. Но остерегайтесь висящих ссылок.

person Mahesh    schedule 28.11.2011

Вы освобождаете память, когда она вам больше не нужна. Если это происходит до выхода из программы, вы освобождаете ее перед возвратом. Если программа хочет продолжить что-то, и вам больше не нужно дерево, вы освобождаете его и продолжаете работу с программой.

Если, например, связанные списки в дереве могут на каком-то этапе сократиться, неиспользуемые узлы должны быть немедленно освобождены.

person Shahbaz    schedule 28.11.2011

Вы можете освободить все данные, как только они вам больше не понадобятся, например, когда вы закончите их печатать. В вашем случае, если это все, что вы программируете, это не имеет большого значения, так как ваше ядро ​​​​освободит всю память, выделенную вашей программой при завершении. Однако имеет значение, если программа продолжает работать, поскольку это означает, что вы потребляете память, которую нельзя использовать для других программ.

Это немного похоже на предыдущую версию Firefox, где он не освобождал память после закрытия вкладки. Программа продолжала запрашивать все больше и больше памяти, не освобождая ее.

person Quentin Casasnovas    schedule 28.11.2011

Как все говорят выше, освобождайте его, когда он вам больше не нужен, но, кроме того, часто полезно попытаться освободить на том же уровне, который вы создаете. Это сложнее, когда вы передаете ссылки и тому подобное.

person Irony    schedule 29.11.2011