2014-02-08 4 views
0

Я пытаюсь получить зависание c, и я не могу понять, почему этот код создает segfault.Почему передача структуры таким образом создает segfault?

// In src/test.c 

#include <stdio.h> 

typedef struct { 
    int length; 
    int *arr[1000]; 
} Stack; 

void push(Stack *stack, int el) { 
    (*stack->arr)[stack->length++] = el; 
} 

int pop(Stack *stack) { 
    return (*stack->arr)[--stack->length]; 
} 

int main(int argc, char* argv[]) { 
    Stack stack; 
    push(&stack, 5); 
    printf("%d\n", pop(&stack)); 
    return 0; 
} 

Тогда я скомпилировать и запустить:

$ gcc src/test.c -o test && ./test 
[1] 79484 segmentation fault ./test 
+0

Ну, какая строка вызывает ошибку ??? – OldProgrammer

+0

Я даже не знаю, как это узнать, но, судя по коду, я уверен, что это функция 'push' или' pop'. Все еще * очень * новичок в c. – benekastah

+2

Вы не инициализируете 'stack.length'. (И скомпилировать с '-g' и использовать' gdb' для отладки.) – Mat

ответ

4

У вас есть несколько проблем.

Как и многие другие, ваш int length struct member никогда не устанавливается в ноль и, следовательно, может содержать что угодно.

Вы должны установить длину до 0.

Во-вторых, int *arr[1000] является массивом integer pointers. Так что просто присвоение int определенной позиции массива неверно.

Вы хотите что-то больше, как это:

// In src/test.c 

#include <stdio.h> 

typedef struct { 
    int length; 
    int arr[1000]; // Code change (create an array of integers) 
} Stack; 

void push(Stack *stack, int el) { 
    stack->arr[stack->length++] = el; // Code change (no need for additional 
             // structure member dereference). 
} 

int pop(Stack *stack) { 
    return stack->arr[--stack->length]; // Code change (no need for additional 
             // structure member dereference). 
} 

int main(int argc, char* argv[]) { 
    Stack stack; 
    stack.length = 0; // Code change (set the starting length value to 0) 
    push(&stack, 5); 
    printf("%d\n", pop(&stack)); 
    return 0; 
} 
1

В вашей структуре, "длина" никогда не инициализируется, поэтому она содержит мусор. После чего вы ссылаетесь:

(*stack->arr)[stack->length++] 

это индексирование памяти в неопределенном месте. Таким образом, вам нужна некоторая функция, например init_stack(), чтобы инициализировать члены данных структур для известных значений (например, нуль).

1

Тип массива в структуре неправильный; это должно быть int arr[1000];.

Как написано, вы используете неинициализированные переменные повсюду; ни length, ни любые указатели в вашем arr не настроены ни на что надежное (хотя указатели должны быть равными int). Поскольку у вас есть указатели вместо int в вашем стеке, у вас есть очень сложное выражение для доступа к стеку ((*stack->arr)[stack->length++] и т. Д.), Что должно быть намного проще, как в этом переписанном коде ниже.

#include <stdio.h> 

typedef struct 
{ 
    int length; 
    int arr[1000]; 
} Stack; 

void push(Stack *stack, int el) 
{ 
    stack->arr[stack->length++] = el; 
} 

int pop(Stack *stack) 
{ 
    return stack->arr[--stack->length]; 
} 

int main(void) 
{ 
    Stack stack = { 0, { 0 } }; 
    push(&stack, 5); 
    printf("%d\n", pop(&stack)); 
    return 0; 
} 
0
#include <stdio.h> 

typedef struct { 
    int length; 
    int arr[1000]; 
} Stack; 

void push(Stack *stack, int el) { 
    (stack->arr)[stack->length++] = el; 
} 

int pop(Stack *stack) { 
    return (stack->arr)[--stack->length]; 
} 


int main(int argc, char* argv[]) { 
    Stack stack; 
    memset(&stack,0,sizeof(Stack)); 
    push(&stack, 5); 
    printf("%d\n", pop(&stack)); 
    return 0; 
} 

Правило большого пальца является выделение памяти перед доступом к ней.

+0

Скобки в '(stack-> arr) [stack-> length ++]' на самом деле не нужны, хотя на самом деле они неверны. Использование 'memset()' вместо инициализатора работает, но компилятор может сделать работу лучше. –

Смежные вопросы