Как правильно освободить вложенные структуры данных? - PullRequest
0 голосов
/ 10 апреля 2019

У меня есть небольшая программа, которая создает связанный список, узлы которого содержат (указатели) двоичные деревья. Когда я выхожу из программы, я, очевидно, хочу освободить эту память, сначала я подумал, что мне нужно освободить все узлы дерева и дерево, и только тогда я смогу освободить члены связанного списка, иначе у меня будет утечка памяти. Это неверно? Нужно ли только освобождать узлы связанного списка, и поскольку они указывают на двоичные деревья, деревья автоматически освобождаются?

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

Вот выдержка из некоторого кода, речь идет о функции destroy_list(), я просто хочу знать, если пропуск вызова destroy_tree() правильно освободит мою память.

typedef struct listNode
{
    char* name;
    BST* customers;
    struct listNode *next;
} ListNode;

typedef struct list
{
    ListNode* head;
} List;

typedef struct bstnode
{
    long data;
    struct bstnode* left_node;
    struct bstnode* right_node;
} bstNode;

typedef struct bst
{
    bstNode* root;
} BST;

void destroy_list(List *self)
{
    ListNode* cursor = self->head;
    ListNode* prev = NULL;

    while (cursor != NULL)
    {
        prev = cursor;
        cursor = cursor->next;
        destroy_tree(prev->customers);
        free(prev);
    }
    self->head = NULL;
}

void destroy_tree_node(bstNode* self)
{
    if (self == NULL)
        return;
    destroy_tree_node(self->left_node);
    destroy_tree_node(self->right_node);
    free(self);
}

void destroy_tree(BST* self)
{
    destroy_tree_node(self->root);
    free(self);
}

Спасибо за вашу помощь!

РЕДАКТИРОВАТЬ: Я только что закомментировал строку, и она все еще падает. Я должен был провести еще какое-то расследование, прежде чем публиковать вопрос, но я собираюсь оставить его, поскольку я все еще заинтересован в ответе на вопрос о том, должен ли BST быть свободным независимо от списка или нет.

1 Ответ

0 голосов
/ 10 апреля 2019

Пропуск звонка на destroy_tree не освободит вашу память.

Я вижу только две возможности. Либо destroy_tree нужно бронировать против NULL, либо у вас есть куча повреждений в другом месте. Броня вроде так:

void destroy_tree(BST* self)
{
    if (!self) return;
    destroy_tree_node(self->root);
    free(self);
}
...