user1798299
user1798299

Reputation: 183

Delete items from linked list causes segmentation fault

I have an issue where I am trying to delete an entry from a linked list but it causes a segmentation fault no matter where I try to delete the item from (head, middle, or tail). I'm not sure where the issue lies.

    void
    add_to_list(struct linked_list *list, int x)
    {
        struct node *n = malloc(sizeof *n);
        n->data = x;
        n->next = NULL;
        if (list->head == NULL)
            list->head = n;
        if (list->tail != NULL)
            list->tail->next = n;
        list->tail = n;
    }
    void
    remove_from_list(struct linked_list *list, int position)
    {
        struct node *current_node = list->head;
        struct node *previous_node = NULL;
        int i;
        for (i = 0; i < position; i++) {
            previous_node = current_node;
            current_node = current_node->next;
        }
        if (position == 0) {    // removing the head means we have to
                        // update the head pointer
            list->head = list->head->next;
        } else {
            previous_node->next = current_node->next;
        }
        free(current_node);
        if (list->tail == current_node) // remove the last element means
                    // updating the tail pointer
            list->tail = previous_node;
    }

    int
    main(void)
    {
        struct linked_list list = { .head = NULL, .tail = NULL };
        add_to_list(&list, 'h');
        add_to_list(&list, 'e');
        add_to_list(&list, 'l');
            add_to_list(&list, 'l');
            add_to_list(&list, 'o');
        remove_from_list(&list, 'e');
        add_to_list(&list, 's');
        print_list_rec(&list);  // print_nodes_rec(list.head)
        free_list(&list);
        return 0;
    }

Upvotes: 0

Views: 742

Answers (2)

simonc
simonc

Reputation: 42205

The call

remove_from_list(&list, 'e');

specifies 'e' as a position in the list. The ascii value of 'e' is 101; you have 5 items in the list.

remove_from_list iterates through the list position times without checking whether it has reached the end.

You need to change this to either have the caller pass the index they want to remove or, better, change the second argument to be the item value to search for and modify the for loop in remove_from_list to exit when it finds this value.

void remove_from_list(struct linked_list *list, int data)
{
    struct node *current_node = list->head;
    struct node *previous_node = NULL;
    while (current_node != NULL) {
        if (current_node->data == data) {
            break;
        }
        previous_node = current_node;
        current_node = current_node->next;
    }
    if (previous_node == NULL) { // removing the head means we have to

In either case, it'd be safer if remove_from_list also guarded against reading beyond the end of its list

Upvotes: 2

Tripp Kinetics
Tripp Kinetics

Reputation: 5459

It appears that you are not checking whether you've reached the end of the list, and you might be trying to free a NULL pointer.

Upvotes: 0

Related Questions