删除通用双端队列的第一个节点时出现分段错误(核心已转储)
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);
函数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);