Search code examples
csegmentation-faultqueuedoubly-linked-list

Segmentation fault ( core dumped) while removing first node of generic double ended queue


segmentation fault occurs in the function void removeFirst(queue *q,void *toRet) while accessing the prev pointer of head using q->head->prev = NULL;. The fault doesn't occur while accessing prev nodes of other nodes. For instance in function void removeLast(queue *q,void *toRet) the call q->tail = q->tail->prev; works fine.

Here is the complete code

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdbool.h>
#include <string.h>
typedef struct _data {
    void * data;
    struct _data *next;
    struct _data *prev;
}data;

typedef struct _queue {
    size_t size;
    size_t allocationSize;
    data* head;
    data* tail;
}queue;


bool isEmpty(queue *q) {
    if (q == NULL) 
        return NULL;
    
    if (q->size == 0) 
        return true;
    
    else
    return false;
}

queue *Deque(size_t allocSize) { 
    queue *q = (queue *)malloc(sizeof(queue));
    if (q == NULL)
    return NULL;
    q->allocationSize = allocSize;
    q->size = 0;
    q->head = q->tail = NULL;
    return q;
}

void addFirst(queue *q, void *_data) {  
if (q == NULL){ 
        fprintf(stderr, "Queue can't be null");
        exit(-1);
    }

    data *toInsert = (data*)malloc(sizeof(data));
    if (toInsert == NULL) {
        fprintf(stderr, "Error allocating memory");
        exit(-1);
    }
    toInsert->data = malloc(q->allocationSize);
    if (toInsert->data == NULL)
    {
        fprintf(stderr, "Error allocating memory");
        exit(-1);
    }
    toInsert->next = NULL;
    toInsert->prev = NULL;  

    memcpy(toInsert->data, _data, q->allocationSize);

    if (q->size == 0) //First insertion
        q->head = q->tail = toInsert;
        
    else { 
       toInsert->next = q->head->next;
        q->head = toInsert;
    }
  q->size++;
}

void removeFirst(queue *q,void *toRet)
{ 
    if (q == NULL || isEmpty(q)){
        fprintf(stderr, "Queue is null or empty");
        exit(-1);
    }

    data *toDel = q->head;
    if (q->size == 1) {
        memcpy(toRet, toDel->data, q->allocationSize);
        free(toDel->data);
        free(toDel);
        q->head = q->tail = NULL;
        q->size--;
        return;
    }
    q->head = q->head->next;
    q->head->prev = NULL; //segmentation fault occurs here
    memcpy(toRet, toDel->data, q->allocationSize);
    free(toDel->data);
    free(toDel);
    q->size--;
}

struct temp {
    int a;
    int b;
};
int main () {
    struct temp t;
    queue *q= Deque(sizeof(struct temp));
    t.a=10;
    addFirst(q,&t);
    t.b=10;
    addFirst(q,&t);
    t.a=20;
    addFirst(q,&t);
    t.b=9;
    removeFirst(q,&t); //Unable to perform
    return 0;
}


Solution

  • q->head->prev = NULL; //segmentation fault occurs here

    The segmentation fault happens because the first node has prev == NULL. This patch fixes the crash (only memory leaks remain):

    --- t.c 2020-07-19 17:57:41.255993955 -0700
    +++ t1.c        2020-07-19 18:05:28.278502979 -0700
    @@ -87,7 +87,8 @@
             return;
         }
         q->head = q->head->next;
    -    q->head->prev = NULL; //segmentation fault occurs here
    +    if (q->head != NULL)
    +      q->head->prev = NULL;
         memcpy(toRet, toDel->data, q->allocationSize);
         free(toDel->data);
         free(toDel);