【问题标题】:Why is this queue implementation in C giving segmentation fault?为什么 C 中的这个队列实现会产生分段错误?
【发布时间】:2017-01-08 17:54:54
【问题描述】:

我已经在 C 中实现了一个简单的队列,但是当我在出队后尝试访问 Q.front 时,它给出了分段错误(例如,参见 int main())。

更准确地说,问题发生在我 -

  1. 将单个元素排入队列。
  2. 出队。
  3. 将一个或多个元素排入队列。
  4. 尝试访问Q.front

但是当我 -

  1. 将多个元素加入队列。
  2. 出队一次。
  3. 将更多元素加入队列(可选)
  4. 访问Q.front成功。

所以这是我的完整程序 -

#include <stdio.h>
#include <stdlib.h> //for malloc

struct qnode
{
    int r;
    struct qnode *link;
};

typedef struct qnode qNode;

typedef struct
{
    qNode *front;
    qNode *rear;
    int qsize;
}QUEUE;

QUEUE initializeQueue(void)
{
    QUEUE q;
    q.front = NULL;
    q.rear = NULL;
    q.qsize = 0;
    return q;
}


qNode *createQueueNode(int e)
{
    qNode *temp;
    temp = (qNode *) malloc(sizeof(qNode));
    if(temp == NULL)
    {
        printf("INSUFFICIENT MEMORY\n");
        exit(0);
    }
    temp->r = e;
    temp->link = NULL;
    return temp;
}
QUEUE enqueue(QUEUE q, int e)
{
    if(q.rear == NULL)
    {
        q.rear = createQueueNode(e);
        q.front = q.rear;
        q.qsize++;
    }
    else
    {
        q.rear->link = createQueueNode(e);
        q.rear = q.rear->link;
        q.qsize++;
    }
    return q;
}

QUEUE dequeue(QUEUE q)
{
    qNode *temp;
    if(q.front == NULL)
    {
        printf("queue is empty\n");
        exit(0);
    }
    else
    {
        temp = q.front;
        q.front = q.front->link;
        free(temp);
    }

    q.qsize--;
    return q;
}



int main(){

    QUEUE Q = initializeQueue();
    Q = enqueue(Q, 2);
    printf("%d\n",Q.front->r);
    Q = dequeue(Q);
    Q = enqueue(Q,4);
    printf("%d\n",Q.front->r); // This line is giving segmentation fault 

    return 0;
}

【问题讨论】:

    标签: c segmentation-fault queue priority-queue


    【解决方案1】:
    Program terminated with signal 11, Segmentation fault.
    #0  0x0000000000400859 in main () at ./2.c:87
    87          printf("%d\n",Q.front->r); // This line is giving segmentation fault 
    Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.80.el6.x86_64
    (gdb) p Q
    $1 = {front = 0x0, rear = 0x1636010, qsize = 1}
    

    front 为空,您可以访问它。 你只需要一个像 gdb 这样的调试器来看看你的程序出了什么问题。

    【讨论】:

    • 但是如果我在出队操作后又加入了一个元素,它怎么会为空呢?
    【解决方案2】:

    dequeue 将 q.front 设置为 NULL(来自 q.front->link,之前在 createQueueNode 中设置为 NULL)并在 q.rear 中留下一个垃圾指针(指向 free() 的内存)。由于 q.rear 不为 NULL,因此 enqueue 中的 if 语句中的第二个块在第二次调用 enqueue 时执行。它写入 free() 的内存(q.rear->link),然后将其取消引用到 q.rear。我很惊讶它并没有崩溃,实际上,写入 free() 的内存。如果队列为空,快速修复可能是在 dequeue 中将 q.rear 设置为 NULL。您还应该添加一个健全性检查,以便 dequeue 不会在空队列上运行。

    此外,您还有一种有趣的方式来传递该结构,就像烫手山芋一样。为什么不通过引用传递它并就地修改而不是返回它?

    【讨论】:

      猜你喜欢
      • 2011-01-27
      • 2013-05-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-14
      • 1970-01-01
      • 2016-01-09
      • 2013-03-28
      相关资源
      最近更新 更多