Почему эта функция уничтожения выбрасывает ошибку сегментации в единый связанный список? - PullRequest
0 голосов
/ 14 февраля 2020

Я новичок в структурах данных и C. этот код корректно работает при создании и вставке узла, но когда я вызываю функцию destroy, его случай a Segmentation Fault. Кажется, он работает правильно, если я помещаю весь код в основную функцию вместо других функций.

В каких случаях эта ошибка:

destroy

delete IF удалил только заголовок связанного списка

Может кто-нибудь объяснить мне, что с этим не так?

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

typedef struct node
{
    int value;
    struct node *next;
} node;

node *create_node(int value);
unsigned char insert(node *head, int value);
unsigned char delete_node(node *head, node *old_node);
node *search(node *head, int value);
unsigned char destroy(node *head);

int main(void)
{
    node *head = create_node(1);
    insert(head, 3);
    insert(head, 2);

    destroy(head);

    for(node *i = head; i != NULL; i = i -> next)
    {
        printf("%i\n", i -> value);
    }
}

// Will create a node and return it if succeeded else it will return NULL
node *create_node(int value)
{
    node *new_node = malloc(sizeof(node));

    // Check if the node created successfully or not
    if (new_node == NULL)
    {
        return NULL;
    }

    new_node -> value = value;
    new_node -> next = NULL;

    return new_node;
}

// Insert the node to a list at the beginning of it, return 0 if succeed else number NOT 0
unsigned char insert(node *head, int value)
{
    node *new_node = create_node(value);

    // Check if the node created successfully or not
    if (new_node == NULL)
    {
        return 1;
    }

    // Check if the List is exist or not
    if (head == NULL)
    {
        return 2;
    }

    new_node -> next = head -> next;
    head -> next = new_node;

    return 0;
}

// Delete the node, return 0 if succeeded else number NOT 0
unsigned char delete_node(node *head, node *old_node)
{
    // Check if the node is exist or not
    if (old_node == NULL)
    {
        return 1;
    }

    node *back = head;

    // If delete the first node ONLY
    if (head == old_node)
    {
        free(old_node);
        old_node = NULL;
        return 0;
    }

    while (back -> next != old_node)
    {
        back = back -> next;
    }

    back -> next = old_node -> next;
    free(old_node);

    return 0;
}

// destroy the whole linked list, returns 0 if destroid successfully else number NOT 0
unsigned char destroy(node *head)
{
    // Check if the List is exist or not
    if (head == NULL)
    {
        return 1;
    }

    node *temp = head;

    while (temp != NULL)
    {
        temp = temp -> next;
        destroy(temp);
        delete_node(head, temp);

    }

    delete_node(head, head);

    return 0;
}

// return Pointer to node if founded it else return NULL
node *search(node *head, int value)
{
    while (head != NULL)
    {
        // If founded it return it's pointer
        if (head -> value == value)
        {
            return head;
        }
        else
        {
            head = head -> next;
        }
    }
    return NULL;
}

Ответы [ 2 ]

0 голосов
/ 14 февраля 2020

ваша проблема здесь:

while (temp != NULL)
{
   temp = temp -> next;
   delete_node(head, temp);
}  

ваша функция delete_node(node *head, node *old_node) в конце выполнения:

free(old_node); // you free temp !

и вы не установите old_node на NULL, если вы свободны эта память, вы не можете l oop второй раз здесь (потому что временная удалена):

while (temp != NULL)
{
   temp = temp -> next;
   delete_node(head, temp);
} 
0 голосов
/ 14 февраля 2020

Я не вижу точно, в чем здесь проблема, но я заметил, что ваша distroy (si c ...) излишне сложна. Если ваша цель - уничтожить весь список, вам не нужно вызывать подпрограмму destroy_node. Просто сделайте что-то вроде этого: (псевдокод ...)

while (head != NULL) {
   temp = head->next;
   free(head);
   head = temp;
}

Ваша destroy_node процедура также выглядит излишне сложной. Необходимо рассмотреть только два случая: удаление узла head и удаление узла, который не является головным узлом. (псевдокод)

if (node == NULL) return;
if (node == head_node) {
   head_node = head_node->next;
   free(node);
} else {
   temp = head_node;
   while ((temp != NULL) {
     if (temp->next == node) {
        temp->next = temp->next->next;  // link it out of the list
        free(node);
        return;
     } else {
        temp = temp->next;
     }
  }
}
...