【问题标题】:Why this destroy function throw Segmentation Fault in single linked list为什么这个destroy函数在单链表中抛出Segmentation Fault
【发布时间】:2020-02-13 21:41:05
【问题描述】:

我是数据结构和 C 的新手。这段代码在创建和插入节点时可以正常工作,但是当我调用破坏函数时,它的情况是 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;
}

【问题讨论】:

  • 快速样式点,不要在指针声明node * head的两边加空格,看起来你是在尝试将它们相乘。
  • 段错误发生在哪一行代码上?在调试器中运行程序将立即为您提供该信息。一旦您进入调试器,您就可以转储更多状态并跟踪程序执行以帮助您找到问题。
  • 此外,还缺少一些代码,例如 create_nodeinsert。所有请求调试帮助的 Stack Overflow 问题都需要minimal verifiable example。否则,您可能会遗漏一些实际导致问题的代码,并且还会使其他人难以运行代码以自己查看/调试问题。

标签: c pointers data-structures segmentation-fault


【解决方案1】:

我不知道问题出在哪里,但我确实注意到您的distroy (sic...) 函数过于复杂。如果您的目的是销毁整个列表,则无需调用destroy_node 例程。只需执行以下操作:(pseudocode ...)

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;
     }
  }
}

【讨论】:

    【解决方案2】:

    你的问题在这里:

    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,你不能在这里循环第二次(因为临时删除了):

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

    【讨论】:

    • 错误地,我使用了delete_node 而不是destroy 我打算使用递归算法。但不管怎样,修​​复代码后bug依然存在。
    • @OmarAhmed 你能更新你的代码吗(在帖子中)请看看你做了什么修改
    猜你喜欢
    • 2021-08-06
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    • 2015-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多