Ошибка сегментации с очередью в C - PullRequest
1 голос
/ 11 мая 2010

Я получаю ошибку сегментации со следующим кодом после добавления структур в мою очередь.

Ошибка сегментации возникает, когда 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

Ответы [ 5 ]

4 голосов
/ 11 мая 2010

Я думаю, что ваша проблема лежит здесь:

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

Вы масштабируете next_index по размеру вашей структуры, но это то, что автоматически выполняется этим вторым утверждением - *(queue + (next_index)) эквивалентно queue[next_index], и последнее более читабельно для всех, кроме тех, кто использовал C, так как K & R был впервые опубликован: -)

Другими словами, next_index должно быть значением от 0 до MAX_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 в конечном готовом к использованию коде, да?

1 голос
/ 11 мая 2010

Вы умножаете next_index на sizeof(struct myInfo), что не обязательно. Когда вы добавляете к типу указателя, смещение автоматически рассчитывается по размеру указываемого объекта. Изменение первой строки push() должно быть достаточным:

int next_index = (queue_size + queue_head) % MAX_QUEUE;
0 голосов
/ 11 мая 2010

Вы можете рассматривать очередь как массив, и тогда будет просто выдвинуть элементы:

void push(struct myInfo info) {
   if (queue_size < MAX_QUEUE) {
     printf("Pushing %s to %d\n", info.data, queue_size);
     queue[queue_size] = info;
     queue_size++;
   } else {
     printf("ERROR: Queue is full.\n");
     /* alternatively you could have a queue_insertion_point
        variable to keep track of where you are in the queue
        and use that as your index into your array. You'd then
        reset it to 0 (to wrap around) when it hit MAX_QUEUE. 
        You need to ensure you don't overwrite data currently
        in the queue by comparing it against queue_head */
   }
}
0 голосов
/ 11 мая 2010
*(queue + (next_index)) = info;

queue - указатель на struct myInfo. Вам нужно только добавить 1, чтобы получить следующий адрес - вы воспринимаете это как char *.

Вы можете просто сделать:

*(queue + queue_size++) = info;
0 голосов
/ 11 мая 2010
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);
        }
}
...