Search code examples
ccircular-list

Segmentation Fault in Circular Linked List


I am writing code for the insertion into a circular linked list but getting segmentation error at line 110. I have checked the code but cant find the reason for the segmentation error the code checks the linked list with circular queue. If it matches then it prints correct else the given case based outputs

The code in the insertions is the code I have doubt with.

//-------------------- head of the code ------------------------

#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#define in(x) scanf(" %d", &x);
#define LinkedListNode LinkedListNode
typedef struct LinkedListNode LinkedListNode;
struct LinkedListNode {
  int val;
  struct LinkedListNode* next;
};


//-------------------- body of the code ------------------------

LinkedListNode* insertAtBeginning(LinkedListNode* tail, int val) {
  if(tail==NULL){
    tail->val = val;
    tail->next = tail;
  }
  else{
    LinkedListNode* p = (LinkedListNode*)malloc(sizeof(LinkedListNode));

    p->val = val;
    p->next = tail->next;
    tail->next = p;
  }

  return tail;
}

LinkedListNode* insertAtEnd(LinkedListNode* tail, int val) {
  if(tail==NULL){
    tail->val = val;
    tail->next = tail;
    return tail;
  }
  else{

    LinkedListNode* p = (LinkedListNode*)malloc(sizeof(LinkedListNode));

    p->val = val;
    p->next = tail->next;
    tail->next = p;
    tail = p;
    return tail;
  }

}


//-------------------- tail of the code ------------------------

int rng(int lim) {
  if (lim == 0) return 0;
  return rand()%lim;
}

int a[1005], sz = 0;
void insertt(int val, int pos) {
  if (pos < 0) return;
  if (pos > sz + 1) return;
  sz += 1;
  for (int i = sz; i > pos; i--)
  a[i] = a[i - 1];
  a[pos] = val;
}

void erasee(int pos) {
  if (pos > sz) return;
  if (pos < 1) return;
  sz--;
  for (int i = pos; i <= sz; i++)
  a[i] = a[i + 1];
}

int check(LinkedListNode* tail) {
  if (tail == NULL && sz == 0) return 1;
  if (tail == NULL || sz == 0) return 0;
  if (tail->val != a[sz]) return 0;
  LinkedListNode* ii = tail->next;
  for (int i = 1; i < sz; i++) {
    if (ii == NULL) return 0;
    if (a[i] != ii->val) return 0;
    ii = ii->next;
  }
  return 1;
}

int main() {
  srand(time(NULL));
  int t, n; in(t); in(n);
  while (t--) {
    LinkedListNode* head = NULL;
    sz = 0;
    for (int i = 0; i < n; i++) {
      int type = rng(4);
      if (type == 0) {
        int val = rng(1000);
        head = insertAtBeginning(head, val);
        insertt(val, 1);
        if (!check(head)) {
          printf("incorrect insertAtBeginning");
          return 0;
        }
      }

      if (type == 1) {
        int val = rng(1000);
        head = insertAtEnd(head, val);
        insertt(val, sz + 1);
        if (!check(head)) {
          printf("incorrect insertAtEnd");
          return 0;
        }
      }

    }
  }
  printf("correct");
}

I am getting the following error

Reading symbols from Solution...done.
[New LWP 83892]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `./Solution'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  insertAtEnd (val=<optimized out>, tail=0x0) at Solution.c:110

Solution

  • The problem is here

    if(tail==NULL){
        tail->val = val;
        tail->next = tail;
        return tail;
    }
    

    If tail is a null pointer you directly dereference this null pointer. That leads to undefined behavior- You still need to allocate a new node.

    You have the same problem with both the insertAtEnd and the insertAtBeginning function. And in the insertAtBeginning function you for some reason have the badly named tail variable (which is supposed to be the head pointer).


    Another problem:

    head = insertAtEnd(head, val);
    

    You're supposed to pass (and assign to) the tail pointer here. But you don't have any such pointer.