Reputation: 183
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
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
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