Reputation: 13
I'm experiencing some trouble with an assignment. I am supposed to implement a dynamically growing stack that doubles its size when it's full and halves it when it's 1/4 full. Since I am a total C beginner and are unfamiliar with pointers, I've looked through some examples and this is the Code I came up with.
It actually compiles in gcc without warnings, but produces a "Segmentation fault" when I try to run it. I found out that this probably has to do with broken pointers, but I don't see any mistakes and would be glad if someone could point it out for me.
Cheers
# ifndef STACK_H
# define STACK_H
# include "stdlib.h"
typedef struct stack {
int *stack;
int used;
int size;
} stack;
stack* stck_construct() {
stack *stck;
stck->stack = (int *)malloc(10 * sizeof(int));
stck->used = 0;
stck->size = 10;
return stck;
}
void stck_destruct(stack *stck) {
stck->stack = 0;
stck->used = stck->size = 0;
free(stck);
}
int stck_push(stack *stck, int val) {
if (stck->used == stck->size) {
stck->size *= 2;
stck->stack = (int *)realloc(stck->stack, stck->size * sizeof(int));
}
stck->stack[stck->used] = val;
stck->used++;
return 1;
}
int stck_pop(stack *stck, int *val) {
*val = stck->stack[stck->used];
free(stck->stack);
stck->used--;
if (stck->used <= (stck->size)/4) {
if (stck->size <=40) stck->size = 10;
else stck->size /= 2;
stck->stack = (int *)realloc(stck->stack, stck->size * sizeof(int));
}
return 1;
}
int main(){
stack* test;
test=stck_construct();
int i; int out;
for (i =1; i<=10; i++)
stck_push(test, i);
for (i =1; i<=10; i++) {
stck_pop(test,&out);
printf("%i\n", out);
}
stck_destruct(test);
return 0;
}
# endif
Upvotes: 1
Views: 661
Reputation: 62106
Bugs annotated:
stack* stck_construct() {
// stck is a pointer, you never initialize it to point to an existing object:
stack *stck;
// you dereference the invalid pointer with stck->stack:
stck->stack = (int *)malloc(10 * sizeof(int));
stck->used = 0;
stck->size = 10;
return stck;
}
void stck_destruct(stack *stck) {
stck->stack = 0;
stck->used = stck->size = 0;
// I thought you were assigning the pointer to the allocated memory to stck->stack,
// and by now that pointer is 0 as you just did stck->stack = 0;
free(stck);
}
if (stck->used == stck->size) {
stck->size *= 2;
// if realloc() fails you end up with twice as big stck->size and
// with stck->stack = NULL
stck->stack = (int *)realloc(stck->stack, stck->size * sizeof(int));
}
// You first store the new element and then advance the index
stck->stack[stck->used] = val;
stck->used++;
// But when you remove it you don't do the two operations in the reverse order:
*val = stck->stack[stck->used];
// and for some reason you additionally destroy all data
free(stck->stack);
stck->used--;
// and then you realloc() using the invalid pointer (you just free()'d it!)
stck->stack = (int *)realloc(stck->stack, stck->size * sizeof(int));
Upvotes: 2
Reputation: 372
In stack* stck_construct()
you're using stck->
without having created stck
first. As it is, it's only a pointer referencing nowhere. This will surely produce a Segmentation Fault. You're confusing a stack*
with an actual stack
(or maybe you just forgot to malloc
the whole thing :)
N.B: There are also some other bugs roaming around which I didn't mention. See David's and Alexey's comments if you're interested.
Upvotes: 4