简体   繁体   中英

Linked list in C: Why am I segfaulting?

I'm new to C and have been working on writing a linked list by hand. Right now, I am working on a method to remove an element from the front of the list. It reads:

   void remove_from_front(List *l)
    {
      Node *head = l->first;

      l->first = l->first->next;

      free(head);
    }

I'm sure this is something obvious, but I'm not getting it. Here is some relevant data on my question:

Prior research. I have looked through multiple SO posts, including this one , but all use different implementations that I can't seem to pick apart. There are examples of this code all over the internet, but I do not understand how they work, and would rather learn what my code is doing wrong.

Relevant code snippets. Here is the rest of the code in my program:

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

typedef struct Node{
  void *element;
  struct Node *next;
  struct Node *prev;
} Node;

typedef struct List{
  struct Node *first;
  struct Node *last;
} List;

void add_to_front(List *l, void *toAdd)
{
  Node *n = (Node *)calloc(1, sizeof(Node));
  n->element = toAdd;
  n->next = l->first;
  n->prev = NULL;

  if(l->first != NULL)
    {
      l->first->prev = n;
    }
    l->first = n;
}


void add_to_back(List *l, void *toAdd)
{
  Node *n = (Node *)calloc(1, sizeof(Node));
  n->element = toAdd;
  n->next = NULL;
  n->prev = l->last;

  if(l->last != NULL)
    {
      l->last->next = n;
    }
    l->last = n;
}

void remove_from_front(List *l)
{
  Node *head = l->first;

  l->first = l->first->next;

  free(head);
}

int main(int argc, char *argv[])
{
  List *l = calloc(1, sizeof(List));
  l->first = NULL;
  l->last = NULL;

  add_to_front(l, (void *)'a');
  printf("First element: %c\n", l->first->element);
  add_to_back(l, (void *)'b');
  printf("Last element: %c\n", l->last->element);
  remove_from_front(l);
  printf("New first element: %c\n", l->first->element);
  return 0;
}

Debugger output. Here is the debugger output I get when I run this code.

Valgrind:

==9389== Invalid write of size 4
==9389==    at 0x804852E: remove_from_front (in /home/vagrant/plc/linkedList)
==9389==    by 0x80485D3: main (in /home/vagrant/plc/linkedList)
==9389==  Address 0x8 is not stack'd, malloc'd or (recently) free'd
==9389==
==9389==
==9389== Process terminating with default action of signal 11 (SIGSEGV)
==9389==  Access not within mapped region at address 0x8
==9389==    at 0x804852E: remove_from_front (in /home/vagrant/plc/linkedList)
==9389==    by 0x80485D3: main (in /home/vagrant/plc/linkedList)
==9389==  If you believe this happened as a result of a stack
==9389==  overflow in your program's main thread (unlikely but
==9389==  possible), you can try to increase the size of the
==9389==  main thread stack using the --main-stacksize= flag.
==9389==  The main thread stack size used in this run was 8388608.
==9389==

GDB:

Starting program: /home/vagrant/plc/linkedList
First element: a
Last element: b

Program received signal SIGSEGV, Segmentation fault.
0x0804852e in remove_from_front ()

The output when I run the executable with no debugger is simply:

First element: a
Last element: b
Segmentation fault

I would appreciate any help if possible. Thank you!

The problem is that when you add in the front, if it's the first element in the list, you will need to setup the last pointer, let it pointer to the first element as well, that is, when the list have single element, the first and last should point to the same Node.

// in add_to_front
if (l->last == NULL) {
    l->last = l->first;
}
// add to back:
if (l->first == NULL) {
    l->first = l->last;
}
// in remove from front, check if the list is empty:
if (l->first == NULL)
    return;

Second problem. If removing the last node, clear the last reference

void remove_from_front(List *l)
{
  Node *head = l->first;

  l->first = l->first->next;

  if (!l->first)
  {
    l->last = 0;
  }

  free(head);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM