删除可被 2 整除的节点会导致 SIGSEGV 错误

问题描述

我正在尝试创建一个函数,该函数删除链表中的所有节点,这些节点的值可以被所选数字整除。

代码如下:

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

//add_beg - adds node at beginning
//add_end - adds node at the end
//add_at - adds node at the specified index
//remove_divisible_by - removes node if divisible by num (SIGSEGV)
//print_nodes - prints nodes


struct node
{
    int value;
    struct node *link;
};
typedef struct node node_t;

node_t *head = NULL;

void remove_divisible_by(int num)
{
    node_t *temporary = head;

    while(temporary != NULL) //ERROR IS PROBABLY HERE
    {
        if(temporary->link->value % num == 0) 
        {
            temporary->link = temporary->link->link;
        }

        temporary = temporary->link;

    }
}

void add_at(int index,int value)
{
    node_t *new_node_ptr = calloc(sizeof(node_t),1);

    new_node_ptr->value = value;

    node_t *temporary = head;

    while(index>1)
    {
        temporary = temporary->link;
        index--;
    }

    new_node_ptr->link = temporary->link;
    temporary->link = new_node_ptr;

}

void add_beg(int value)
{
    node_t *new_node_ptr = malloc(sizeof(node_t));

    new_node_ptr->value = value;
    new_node_ptr->link = head;

    head = new_node_ptr;
}

void add_end(int value)
{

    node_t *new_node_ptr;

    new_node_ptr = malloc(sizeof(node_t));

    new_node_ptr->value = value;
    new_node_ptr->link = NULL;

    if(head == NULL)
    {
        head = new_node_ptr;
        return;
    }

    node_t *temporary;
    temporary = head;

    while(temporary->link != NULL) temporary = temporary->link;

    temporary->link = new_node_ptr;


}

void print_nodes(node_t *head)
{
    node_t *temporary;
    temporary = head;
    while(temporary != NULL)
    {
        printf("%d ",temporary->value);
        temporary = temporary->link;
    }
}

int main()
{
    add_end(2);
    add_end(3);
    add_end(5);

    add_beg(1);

    add_at(3,4);

    remove_divisible_by(2);

    print_nodes(head);

    return 0;
}

错误似乎在函数remove_divisible_by

会发生什么: 如果我想删除可被 2 整除的节点,则会收到 SIGSEGV 错误。 如果我想删除列表中的最后一个节点(在这种情况下,可以被 5 整除的数字),它可以工作。

另一方面,如果我在 while(temporary->link != NULL) 函数中写入 remove_divisible_by删除可被数字 2 整除的节点实际上是有效的,但是如果我想删除最后一个,我会收到 SIGSEGV 错误节点(可被 5 整除的节点)

我的问题是,为什么会发生这种情况,我该如何解决

解决方法

Random

... 您不是在检查当前节点 ( if (temporary->link->value % num == 0) { temporary->link = temporary->link->link; } ),而是检查下一个节点 (temporary),它可能不存在(即 temporary->linktemporary->link)因此你的段错误。

始终使用循环中的当前节点。您唯一需要使用 NULL 的时间是在循环结束时,以便切换到下一个节点(如您所做的 temporary->link)。