Указатель, возвращаемый очередью, не может быть разыменован без ошибки сегментации - PullRequest
0 голосов
/ 19 февраля 2019

Я пытаюсь написать очередь.Чтобы проверить это, я поставил пару значений в очередь, которые являются указателями на статически расположенные переменные стека.Когда я распечатываю адрес переменной стека, которая была выдвинута, и указатель, возвращаемый в очередь (соответствует исходной очереди для этого элемента), я получаю то же имя.Когда я разыменовываю указатель на статически размещенную переменную (указатель, который я создаю встроенным с помощью оператора &), он печатает ожидаемое мной значение 10.Но когда я обращаю внимание на указатель, возвращаемый в очередь, которая выглядит как тот же адрес, это вызывает ошибку.Я не совсем уверен, что происходит, мое понимание модели памяти C не может этого объяснить.

Вывод

Storing item at index 0
Queue (head, tail) = 0, 1
1158904628, 0, 0,
Storing item at index 1
Queue (head, tail) = 0, 2
1158904628, 1158904632, 0,
Storing item at index 2
Queue (head, tail) = 0, 0
1158904628, 1158904632, 1158904636,
---------------------------
Enqueued pointer: 45137b34
Enqueued pointer value: 10
Queue (head, tail) = 1, 0
0, 1158904632, 1158904636,
Dequeued pointer: 45137b34
Segmentation fault (core dumped)

Компиляция с gcc -o main queue.c

Код

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

typedef struct {
    int *buffer;
    int size;
    int capacity;
    int head;
    int tail;
} Queue;

void queue_init(Queue *queue, int capacity) {
    void *ptr = malloc((sizeof(void*)) * capacity);
    queue->buffer = ptr;
    queue->capacity = capacity;
    queue->size = 0;
    queue->head = 0;
    queue->tail = 0;
}

void* queue_dequeue(Queue *queue) {
    if (queue->size == 0) return NULL;

    void *item = queue->buffer[queue->head];
    queue->buffer[queue->head] = NULL;
    queue->head = (queue->head + 1) % queue->capacity;
    printf("Queue (head, tail) = %d, %d\n", queue->head, queue->tail);
    queue->size--;

    for (int i = 0; i < 3; i++) {
        printf("%u, ", queue->buffer[i]);
    }
    printf("\n");
    return item;
}

int queue_enqueue(Queue *queue, void *item) {
    if (queue->size == queue->capacity) return -1;

    printf("Storing item at index %d\n", queue->tail);
    queue->buffer[queue->tail] = item;
    queue->size++;
    queue->tail = (queue->tail + 1) % queue->capacity;
    printf("Queue (head, tail) = %d, %d\n", queue->head, queue->tail);

    for (int i = 0; i < 3; i++) {
        printf("%u, ", queue->buffer[i]);
    }
    printf("\n");
}

int main() {
    int a = 10;
    int b = 20;
    int c = 30;

    Queue q;
    queue_init(&q, 3);
    queue_enqueue(&q, &a);
    queue_enqueue(&q, &b);
    queue_enqueue(&q, &c);
    printf("---------------------------\n");

    int *org = &a;
    int *ptr;
    printf("Enqueued pointer: %x\n", org);
    printf("Enqueued pointer value: %i\n", *org);
    ptr = queue_dequeue(&q);
    printf("Dequeued pointer: %x\n", ptr);
    printf("Dequeued pointer value: %i\n", *ptr);

    return 0;
}

1 Ответ

0 голосов
/ 19 февраля 2019

Необходимо изменить int * на void **,
в противном случае целочисленного пространства (4 байта) недостаточно для сохранения void * (8 байтов)
, измененного следующим образом

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

typedef struct {
    void **buffer;
    int size;
    int capacity;
    int head;
    int tail;
} Queue;

void queue_init(Queue *queue, int capacity) {
    void *ptr = malloc((sizeof(void*)) * capacity);
    queue->buffer = ptr;
    queue->capacity = capacity;
    queue->size = 0;
    queue->head = 0;
    queue->tail = 0;
}

void* queue_dequeue(Queue *queue) {
    if (queue->size == 0) return NULL;

    void *item = queue->buffer[queue->head];
    queue->buffer[queue->head] = NULL;
    queue->head = (queue->head + 1) % queue->capacity;
    printf("Queue (head, tail) = %d, %d\n", queue->head, queue->tail);
    queue->size--;

    for (int i = 0; i < queue->size; i++) {
        printf("%p, ", queue->buffer[i]);
    }
    printf("\n");
    return item;
}

int queue_enqueue(Queue *queue, void *item) {
    if (queue->size == queue->capacity) return -1;

    printf("Storing item at index %d\n", queue->tail);
    queue->buffer[queue->tail] = item;
    queue->size++;
    queue->tail = (queue->tail + 1) % queue->capacity;
    printf("Queue (head, tail) = %d, %d\n", queue->head, queue->tail);

    for (int i = 0; i < queue->size; i++) {
        printf("%p, ", queue->buffer[i]);
    }
    printf("\n");
    return 0;
}

int main() {
    int a = 10;
    int b = 20;
    int c = 30;

    Queue q;
    queue_init(&q, 3);
    queue_enqueue(&q, &a);
    queue_enqueue(&q, &b);
    queue_enqueue(&q, &c);
    printf("---------------------------\n");

    int *org = &a;
    int *ptr;
    printf("Enqueued pointer: %p\n", org);
    printf("Enqueued pointer value: %i\n", *org);
    ptr = queue_dequeue(&q);
    printf("Dequeued pointer: %p\n", ptr);
    printf("Dequeued pointer value: %i\n", *ptr);

    return 0;
}
...