C 返回指针后出现SEGFULT

C 返回指针后出现SEGFULT,c,segmentation-fault,C,Segmentation Fault,我用C编写了以下代码,试图开发一个操作系统模拟: c队: typedef enum {running,readyproc,waiting,suspended}status; typedef struct pcb { long pid; char* pname; long priority; long sleepperiod; long* context; status stat; }PCB; typedef enum {ready, timer, su

我用C编写了以下代码,试图开发一个操作系统模拟:

c队:

typedef enum {running,readyproc,waiting,suspended}status;

typedef struct pcb {
   long pid;
   char* pname;
   long priority;
   long sleepperiod;
   long* context;
   status stat;


}PCB;

typedef enum {ready, timer, suspend} queuetype;
typedef struct {
   int size;
   int capacity;
   PCB ** data;
   queuetype qt;
}Queue;

void queue_init(Queue *q, queuetype qt){
   q->size =0;
   q->capacity = QUEUE_INITIAL_CAPACITY ;//100
   q->data = (PCB **)calloc(q->capacity,sizeof(PCB*));
   q->qt = qt;
}

PCB* queue_pop (Queue* q){
   PCB* toReturn;
   int i;
   toReturn = q->data[0];
   for (i=0;i<q->size;i++){
      q->data[i]=q->data [i+1];
   }
  free(q->data[q->size]);
  q->size--;
  printf ("toReturn id:%ld pname: %s\n", toReturn->pid, toReturn->pname);
  return toReturn;
}
编辑: 下面是将填充队列的函数:

void queue_append(Queue *q, PCB* value)
{
   q->data[q->size++] = value;
}
编辑2:
queue\u pop
中返回前的printf返回:

toReturn id: 2 pname: test1c_a
对应于我要从该队列中弹出的内容。

for(I=0;isize;I++){
  for (i=0;i<q->size;i++){
      q->data[i]=q->data [i+1];
   }
q->data[i]=q->data[i+1]; }
如果
q->size==q->capacity
,那么您将运行
q->data
的末尾(它将访问
q->data[q->capacity]
,这是超过其分配长度的长度)


还有很多更有效的方法可以做到这一点。

下面似乎是个问题

free(q->data[q->size]);
假设队列中有两个元素
q->size=2
hold by

q->data[0]
q->data[1]


所以当你打电话的时候。上述代码将释放
q->data[2]
。这可能导致seg故障。

循环(修复长度错误后)是移动多个元件的好方法。明确、正确地表达意图;现代的编译器会像编写
memmove
一样对其进行优化,甚至可能做得更好。(当然,以不同的方式设计数据结构,使弹出不涉及移动任何元素会更好!)这确实是我代码中的一个bug。但这并不能解决我的错误。@m-m——或者可以在数组中保留头和尾索引,完全避免移动@outvader——在您将
数据
元素移过之后,是否应该将数组中的最后一项置空?否则,在空队列上调用
queue\u pop
将返回垃圾。
queue\u pop
永远不会在空队列上调用。我检查队列已满时,如果
q->size==0
,是否
q->size==q->capacity
?如果是这样,
free(q->data[q->size])行将访问分配数组末端以外的元素。(顺便说一句,在这里这么做似乎真的很奇怪。)请发表一篇文章。如果这太费劲了,那么至少要显示队列是如何初始化和填充的。函数
queue_init
通常会初始化队列。
queue_init
会使队列变空,如果在空队列上调用,则您的
pop
函数会中断可能是您错误地释放了队列中的值,或任何其他问题。如果你不发布MCVE,我们就帮不了你。
free(q->data[q->size]);