【问题标题】:Segmentation fault with queue in CC中队列的分段错误
【发布时间】:2010-05-11 14:58:52
【问题描述】:

在将结构添加到队列后,以下代码出现分段错误。

当 MAX_QUEUE 设置为高时会发生分段错误,但当我将其设置为低(100 或 200)时,不会发生错误。自从我上次使用 C 编程已经有一段时间了,因此非常感谢您的帮助。

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

#define MAX_QUEUE 1000

struct myInfo {
        char data[20];
};

struct myInfo* queue;
void push(struct myInfo);
int queue_head = 0;
int queue_size = 0;

int main(int argc, char *argv[])
{
        queue = (struct myInfo*) malloc(sizeof(struct myInfo) * MAX_QUEUE);

        struct myInfo info;
        char buf[10];
        strcpy(buf, "hello");

        while (1)
        {
                strcpy(info.data, buf);
                push(info);
        }
}

void push(struct myInfo info) {
        int next_index = sizeof(struct myInfo) * ((queue_size + queue_head) % MAX_QUEUE);
        printf("Pushing %s to %d\n", info.data, next_index);
        *(queue + (next_index)) = info;
        queue_size++;
}

输出:

Pushing hello to 0
Pushing hello to 20
...
Pushing hello to 7540
Pushing hello to 7560
Pushing hello to 7580
Segmentation fault

【问题讨论】:

  • 由于队列使用静态大小,将其声明为struct myInfo queue[MAXQUEUE] 并使用queue[next_index] 之类的表达式引用元素可能更明智。虽然我也有一段时间没有用 C 编程了。

标签: c queue segmentation-fault


【解决方案1】:

我认为你的问题出在这里:

int next_index = sizeof(struct myInfo) * ...
*(queue + (next_index)) = info;

您将 next_index 按结构的大小缩放,但这是由第二条语句自动完成的 - *(queue + (next_index)) 等效于 queue[next_index],除了我们这些拥有自 K&R 首次发布以来一直在使用 C :-)

换句话说,next_index 应该是从0MAX_QUEUE-1 的值,因此请尝试更改第一条语句以删除与sizeof(struct myInfo) 的乘法:

void push(struct myInfo info) {
    int next_index = (queue_size + queue_head) % MAX_QUEUE;
    printf("Pushing %s to %d\n", info.data, next_index);
    queue[next_index] = info;
    queue_size++;
}

请记住,您最终会在您的无限循环中溢出queue_size。您可能会检查以确保 queue_size 在最终的生产就绪代码中不会增加超过 MAX_QUEUE,是吗?

【讨论】:

  • 谢谢,这就是问题所在!是的,我还有其他代码用于检查 queue_size 并在队列已满时发出警报。在这种情况下它不是一个因素,所以我没有包括它。 :)
【解决方案2】:

您将next_index 乘以sizeof(struct myInfo),这不是必需的。当您添加到指针类型时,偏移量会根据指向对象的大小自动计算。更改push() 的第一行就足够了:

int next_index = (queue_size + queue_head) % MAX_QUEUE;

【讨论】:

    【解决方案3】:
    void push(struct myInfo info) {
            int next_index = (queue_size + queue_head) % MAX_QUEUE;
            printf("Pushing %s to %d\n", info.data, next_index);
            queue[next_index] = info;
            queue_size++;
    }
    

    另外,你不需要那个临时的buf

    int main(int argc, char *argv[])
    {
            queue = (struct myInfo*) malloc(sizeof(struct myInfo) * MAX_QUEUE);
    
            while (1)
            {
                    struct myInfo info; /* Seems you're using C99 so we can declare here */
                    strcpy(info.data, "hello");
                    push(info);
            }
    }
    

    【讨论】:

      【解决方案4】:
      *(queue + (next_index)) = info;
      

      queue 是指向struct myInfo 的指针。您只需向其添加 1 即可获得下一个地址 - 您将其视为 char *

      你可以这样做:

      *(queue + queue_size++) = info;
      

      【讨论】:

      • 不,你不能:队列是循环的,从数组内的索引 queue_head 开始。
      【解决方案5】:

      你可以把 queue 当作一个数组,然后推送项目应该很简单:

      无效推送(结构 myInfo 信息){ if (queue_size

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-03
        • 1970-01-01
        • 2016-03-25
        相关资源
        最近更新 更多