Сбой в программе на C при получении элемента из стека - PullRequest
0 голосов
/ 07 января 2010

Следующий код вылетает при втором Pop() вызове. Я новичок в C, и я больше часа смотрю на этот код и не вижу ошибки. Любые идеи, чтобы помочь мне, почему этот код сбоя?

#include <stdio.h>

#define StackDataSize 100

typedef struct Stack
{
    int index;
    void *data[StackDataSize];
} Stack;

void* Pop(Stack *s)
{
    if(s->index >= 0)
    {
        return s->data[s->index--];
    }
    else
    {
        fprintf(stderr, "ERROR: Stack Empty\n");
        return NULL;
    }
}

void Push(Stack *s, void *v)
{
    if(s->index < StackDataSize)
    {
        s->data[++s->index] = v;
    }
    else
    {
        fprintf(stderr, "ERROR: Stack Full\n");
    }
}

int main(void)
{
    Stack s = {-1}, *intstack = &s;

    int x = 123456;
    Push(intstack, &x);

    printf("%d\n", *(int*)Pop(intstack));
    printf("%d\n", *(int*)Pop(intstack));

    return 0;
}

Ответы [ 7 ]

11 голосов
/ 07 января 2010

Во втором Pop стек пуст, и Pop возвращает NULL, если стек пуст.

Итак, во второй строке:

printf("%d\n", *(int*)Pop(intstack));

вы разыменовываете NULL как указатель на int.

printf("%d\n", *(int*)NULL );
6 голосов
/ 07 января 2010

Второй поп пытается выскочить из пустого стека, а функция Pop() возвращает NULL. Затем основная функция пытается разыменовать этот указатель NULL и вывести значение, на которое она указывает.

Поскольку указатель NULL не указывает на что-либо действительное, вы получаете ошибку сегментации.

3 голосов
/ 07 января 2010

Второй вызов Pop возвращает NULL, который вы затем приводите к int * и пытаетесь разыменовать. Разыменование NULL приводит к segfault.

2 голосов
/ 07 января 2010

Чтобы повторить все предыдущие ответы, проблема в том, что второй вызов Pop возвращает NULL, который вы пытаетесь разыменовать во втором вызове printf ().

На чисто информационной ноте с использованием стеков на основе массива немного проще, если вы растете сверху вниз, а не наоборот:

void Push(Stack *s, void *v)
{
  if (s->index)
    s->data[--s->index] = v;
  else
    // overflow
}

void *Pop(Stack *s)
{
  if (s->index < StackDataSize)
    return s->data[s->index++];
  else
  {
    // underflow
    return NULL;
  }
}
...
Stack s = {StackDataSize, {NULL}};

Таким образом, 0 не становится частным случаем.

1 голос
/ 07 января 2010

Вы пытаетесь разыменовать NULL, который вы возвращаете в пустом регистре.

0 голосов
/ 07 января 2010

Пока я смотрю на ваш код, я вижу еще одну проблему, которая также может привести к сбою: я думаю, что у вас есть ошибка "off by one" на Push(), здесь:

void Push(Stack *s, void *v)
{
    if(s->index < StackDataSize)
    {
        s->data[++s->index] = v;
    }
    ...

Проверка s->index < StackDataSize, затем выполнение предварительного приращения ++s->index и запись в s->data записывает один конец конца массива, если s->index == StackDataSize - 1. Это также даст вам ошибку сегментации.

0 голосов
/ 07 января 2010

Член "index" подписан или не подписан? Если оно не подписано, выражение "s-> index--" приведет к очень большому числу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...