删除通用双端队列的第一个节点时出现分段错误(核心已转储)

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

函数void removeFirst(queue *q,void *toRet) 在使用 q->head->prev = NULL;访问head的prev指针时出现段错误。访问其他节点的prev节点时不会出现该故障。例如在函数 void removeLast(queue *q,void *toRet) 中调用 q->tail = q->tail->prev; 工作正常。

这里是完整的代码

#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;
}

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

分段错误的发生是因为第一个节点有prev == NULL。此补丁修复了崩溃(仅存在内存泄漏):

--- 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);