【问题标题】:C Segmentation fault when I try to enqueue当我尝试入队时出现 C 分段错误
【发布时间】:2014-05-01 02:39:29
【问题描述】:

我正在制作一个生产者/消费者模型,其中生产者需要将 int 值加入队列,而消费者将它们出列。每当我尝试将 int 排入队列时,都会出现分段错误。

这里是相关的队列代码:

#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int item;
    struct Node* next;
} Node;

typedef struct Queue {
    Node* head;
    Node* tail;

    void (*enqueue) (struct Queue* queue, int value);
    int (*dequeue) (struct Queue* queue);
    int (*queueEmpty) (struct Queue* queue);
    int size;
} Queue;

void enqueue (Queue* queue, int item){
    Node* n = (Node*) malloc (sizeof(Node));
    n->item = item;
    n->next = NULL;

    if (queue->head == NULL) { // no head
        queue->head = n;
    } else{
        queue->tail->next = n;
    }
    queue->tail = n;
    queue->size++;
}

Queue* newQueue(){
    Queue* queue;
    queue->size = 0;
    queue->head = NULL;
    queue->tail = NULL;
    queue->enqueue = &enqueue;
    queue->dequeue = &dequeue;
    queue->queueEmpty = &queueEmpty;
    return queue;
}

然后我将其作为prodcons.c 文件中的共享资源:

Queue* queue;

main中初始化:

queue = newQueue();

生产者代码:

void* producer(void* arg) {

    int x;

    for (x = 0; x <= n; x++){
        pthread_mutex_lock(&lock);
        while(queueSize(queue) == maxsize){
            pthread_cond_wait(&lock, &empty)
        }
        enqueue(queue, x);
        pthread_mutex_unlock(&lock);
    }
      return(NULL);
}

【问题讨论】:

  • 您没有为队列分配任何内存。 Queue* queue; 应该是 Queue* queue = malloc(sizeof(Queue));
  • 另外,在 enqueue 中,虽然您检查队列是否有头,但您不会检查队列是否有尾。入队代码似乎用于空队列,但没有初始化该尾部,导致使用 queue->tail->next 时 queue->tail 为 NULL。
  • @Misha 他只在head 为非NULL 时这样做。当你第一次排队时,它会同时设置headtail,所以这应该是安全的(除非dequeue 导致这种情况发生变化)。
  • @Barmar 看起来你是对的。无论哪种方式,您的评论都确定了该错误。
  • 我认为 Johnny Mopp 的评论发现了这个错误。

标签: c data-structures segmentation-fault queue producer-consumer


【解决方案1】:

正如上面Johnny Moppcomment所指出的,分段错误是在这里引起的:

Queue* newQueue(){
    Queue* queue;
    queue->size = 0;   /**** Seg-fault ****/

新定义的队列指针“队列”没有被设置为指向任何特定的东西。因此,它可能指向一些实际上并不存在的奇异内存位置。

被视为指向合法位置,代码尝试将“队列->大小”归零。当处理器计算“奇怪的内存位置”+“struct queue 内的大小元素的偏移量”时,它最终得到了一个不在进程内存映射中列出的地址。这会导致不可恢复的错误,称为分段错误。


修复:

变化:

Queue* newQueue(){
    Queue* queue;

收件人:

Queue* newQueue(){
Queue* queue = malloc(sizeof(*queue));
   /* Check here if malloc() was successful */

【讨论】:

  • 我同意您的回答确定了问题并提供了一个不错的解决方案,并提到了必要的错误检查。当 Johnny Mop 在您创建此答案前一个多小时指出问题时,我只是不确定您是否应该得到信任。如果是我,我可能会创建一个社区 Wiki 答案并链接到发现问题的评论 - 但我接受对我的约束与对你的约束略有不同。
  • @JonathanLeffler,明白了。我对 StackOverflow 有点陌生;到目前为止,我还没有研究过“社区维基答案”方面的事情。我会努力解决这个问题。与此同时,我已经编辑了我的答案,以承认 Johnny Mopp 富有洞察力的评论。感谢您的指导。
猜你喜欢
  • 1970-01-01
  • 2017-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多