Stack with a dynamic array: segfaults when popping value multiple times - c

I have a stack implemented with a dynamically allocated array, which is populated using scanf(). The push function works properly, except that when I print out the stack, I always get two extra zeros at the beginning of the output. Attempting to pop the stack only pops the zeroes, and it segfaults once the popping happens twice. I can't figure out where this issue is occurring.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*Creates struct of stack*/
typedef struct Stack{
int *ptArray;
int top;
int stackSize;
int itemsInStack;
} Stack;
/*Initialized stack*/
Stack* stackInit(){
Stack *a;
a= (Stack*) malloc(sizeof(Stack));
a-> ptArray=(int*) malloc(sizeof(int)) ;
a-> top=0;
a-> stackSize=1;
return a;
}
void stackPush( Stack *stx, int val){
if( (stx->top) == (stx->stackSize)){
grow(&stx->ptArray, &stx->stackSize);
}
stx->ptArray[stx->top]= val;
stx->top++;
stx->itemsInStack++;
}
/*Grows astack array when space runs out*/
void grow(int** array, int *sz){
int *temp;
temp= (int*) malloc(sizeof(int)* (*sz+2) );
int i;
for( i=0; i< *sz; i++)
temp[i]=( *array)[i];
free(*array);
*array= temp;
*sz=*sz+2;
}
void stackPop( Stack* stx){
free(stx->ptArray[stx->top]);
stx->top--;
stx->stackSize--;
stx->itemsInStack--;
}
void showStack(Stack* s){
int i;
printf("\n");
for(i=s->stackSize; i>-1; i--){
printf("%d\n", s->ptArray[i]);
}
}
void main(int argc, char** argv){
Stack *stackArray;
stackArray= stackInit();
int val=0;
while (val != -999) {
scanf("%d", &val);
if (val == -999) {
break;
}
stackPush(stackArray, val);
}
showStack(stackArray);
stackPop(stackArray);
stackPop(stackArray);
showStack(stackArray);
stackPop(stackArray);
showStack(stackArray);
}

You have a problem in your malloc / free couples.
You allocate the array like this :
a-> ptArray=(int*) malloc(sizeof(int)) ;
If you need to grow the stack you allocate a new array like this :
temp= (char*) malloc(sizeof(char)* (*sz+2) );
So you allocate the whole array at one.
But for some reasons , when you are poping an item you do this :
free(stx->ptArray[stx->top]);
You never allocated this. you allocated ptArray so if you have to free something , it is ptArray.
Just like you did in your grow function :
free(*array);
I hope your error is clear now.This is what is causing the segmentation fault. However you still have some issues with the management of your stack.

Related

I'm trying to create a stack in c using structures but my push function doesn't work

I'm trying to create a stack in C using structures but the push() function I wrote is acting strangely. I'm sure it is something obvious that I'm missing but I just couldn't figure out what.
#include <stdio.h>
#define STACK_SIZE 50
typedef struct stack
{
int top;
int items[STACK_SIZE];
}
STACK;
void push(STACK* st, int newitem)
{
st->top++;
st->items[st->top] = newitem;
printf("%d", st->items[st->top]);
}
int main()
{
int n = 1;
STACK* st;
printf("test 1\n");
st->top = -1;
push(st, n);
printf("test 2\n");
return 0;
}
DevCpp only compiles but doesn't execute the code. OnlineGDB runs it but only prints the first test.
This is because your variable STACK* st; was never initialized properly.
Some Important Points:
Don't assign -1 to the length (top), 0 would be better
STACK* st; should be just STACK st;
Your function void push(STACK* st, int newitem) should be declared with static linkage.
Write st->top++
Pass st variable by address to the push() function
Instead of using bare return 0;, use return EXIT_SUCCESS;, which is defined in the header file stdlib.h.
As your total STACK_SIZE is only 50 so, int will be sufficient. But as your STACK_SIZE grows use size_t for your length(top).
use int main(void) { }, instead of int main() { }
NOTE: If STACK_SIZE and top becomes equal means your array is filled completely then further addition of data will lead to Undefined Behavior.
Final Code
#include <stdio.h>
#include <stdlib.h>
#define STACK_SIZE 50
typedef struct stack
{
int top;
int items[STACK_SIZE];
}
STACK;
static void push(STACK* st, int newitem)
{
if(st->top == STACK_SIZE)
{
fprintf(stderr, "stack size reached maximum length\n");
exit(EXIT_FAILURE);
}
st->items[st->top++] = newitem;
printf("%d\n", st->items[st->top - 1]); // we added +1 to `top` in the above line
}
int main(void)
{
int n = 1;
STACK st;
printf("test 1\n");
st.top = 0;
push(&st, n); //pass by address
return EXIT_SUCCESS;
}

Stack implementation is giving Segfault

I am currently writing my own virtual machine. I have to implement the stack. For whatever reason whenever I call sienna_stack_push(processor->stack, 0); it gives me a segfault.
here is the implementation of the stack
#include <stdlib.h>
#include <stdio.h>
#include "stack.h"
// Helper functions
int is_empty(sienna_stack_t* stack){
return stack->top == -1;
}
int is_full(sienna_stack_t* stack){
return stack->top == stack->max_size;
}
void sienna_stack_init(sienna_stack_t* stack, int capacity){
stack = (sienna_stack_t*)malloc(sizeof(sienna_stack_t));
stack->max_size = capacity;
stack->top = -1;
stack->items = (int*)calloc(capacity, sizeof(int));
}
void sienna_stack_push(sienna_stack_t* stack, int value){
if(is_full(stack)){
printf("FATAL: Stack overflow!\n");
exit(-1);
}
stack->items[++stack->top] = value;
}
int sienna_stack_pop(sienna_stack_t* stack){
if(is_empty(stack)){
printf("FATAL: Stack underflow!\n");
exit(-1);
}
return stack->items[stack->top--];
}
int sienna_stack_peek(sienna_stack_t* stack){
return stack->items[stack->top];
}
here is the stack struct definition
typedef struct {
int max_size;
int top;
int* items;
} sienna_stack_t;
here is me using it
#include <stdio.h>
#include "stack.h"
int main() {
sienna_stack_t stack;
sienna_stack_init(&stack, 0xFFFF);
sienna_stack_push(&stack, 0);
}
and the error is saying it is happening when calling sienna_stack_push();
I guess, you want to reserve sizeof(int) * capacity bytes of memory, but in reality you reserve nothing, because the first parameter of calloc() is 0. Thus, you want to access non-reserved memory, that leads to a crash.
EDIT
Your initialisation is wrong. stack is a static variable. When you call init, you pass the address of this variable. Now you assign an new (anonymous) variable that get lost. You could change stack into a pointer variable:
void sienna_stack_init(sienna_stack_t** stack, int capacity){
*stack = (sienna_stack_t*)malloc(sizeof(sienna_stack_t));
(*stack)->max_size = capacity;
(*stack)->top = -1;
(*stack)->items = (int*)calloc(capacity, sizeof(int));
}
// ...
int main(int argc, char *argv[]){
sienna_stack_t *stack;
sienna_stack_init(&stack, 0xFFF);
sienna_stack_push(stack, 0);
}

How to fill a Stack with 0xAA?

I am trying to fill a stack (reserved by malloc) with the value 0xAA or 0b10101010. I think I manage to fill the stack, but printing it, I get different outputs (e83e83e83... or 41f41f41f... for example) depending on my stacksize.
Does anyone have an idea how to solve the problem?
int main(void) {
int status;
int stacksize = 1000;
void* stack=malloc(stacksize);
void* stackTop = stack + stacksize;
for(int i =0; i<stacksize;i++){
stackTop = "10101010";
stackTop --;
}
stackTop =stack + stacksize;
for(int i =0; i<stacksize;i++){
printf("%x", stacksize);
}
return 0;
}
It's somewhat hard to understand from your code and comments, what you're actually trying to do. But if I were to extrapolate on it, you're trying to create a "stack", with an element size of a byte. Here's a quick-and-dirty implementation of such a stack, with bounds checking:
#include <stdio.h>
#include <string.h>
#define STACK_SIZE 1000
struct stack {
int top;
unsigned char elts[STACK_SIZE];
};
static void stack_push(struct stack *s, unsigned char elt) {
if (s->top < STACK_SIZE-1) {
s->elts[s->top++] = elt;
} else {
// No space left in the stack.
}
}
static void stack_pop(struct stack *s) {
if (s->top) {
s->top--;
} else {
// Stack is empty
}
}
static void stack_fill(struct stack *s, unsigned char v) {
memset(s->elts, v, STACK_SIZE);
s->top = STACK_SIZE-1;
}
int main(void) {
// Example driver
struct stack s;
stack_fill(&s, 0xAA);
for (int i = 0; i < STACK_SIZE; i++) {
printf("%d: %02x\n", s.elts[s.top]);
stack_pop(&s);
}
return 0;
}
As an improvement, you could consider e.g. having stack_pop return the popped element, or return some kind of an error if the stack is empty. Or a peek function which returns the top, or an error similar to the one earlier described. However, I omitted them for brevity.
EDIT: To initialize the stack, the only thing required is to set the top member to 0. Initialization function (if needed) is thus trivial to write.
You are filling the stack with strings of chars and reading pointers to them.
The answer given by Paul Hankin in the comment states one of the correct solutions that is using
memset(stack, 0xAA, stacksize);
to fill your stack
thus producing the following code
int main()
{
int status;
int stacksize = 1000;
void* stack = malloc(stacksize);
void* stackTop = stack + stacksize;
memset(stack, 0xAA, stacksize);
for(int i =0; i < stacksize;i++){
printf("%x\n", ((unsigned char*)stack)[i]);
}
return 0;
}

displayStack function printing random letters

I am trying to create a Stack using an Array. I have made all the necessary functions and I have no errors in the console.
however the output from the printf in the displayStack() is
ê #² ` Ç i i q #╨ #. ` Ç x
how can i fix it ?
my code is :
#include <stdio.h>
#include <stdlib.h>
struct Stack {
int top;
char array[];// Array for stack which will store the operators from infx
};
void createStack(struct Stack st){
st.top=-1;
}
void push(struct Stack st,char ch)
{
st.top++;
st.array[st.top]=ch;
}
void displayStack(struct Stack st){
int i;
for (i=st.top;i>=0;i--){
printf("%c\n",st.array[i]);
}
}
char pop(struct Stack st){
char x='x';
if(st.top<0){
printf("Stack UnderFlow\n");
}else{
x= st.array[st.top];
st.top--;
}
return x;
}
int main()
{
struct Stack st;
createStack(st);
push(st,'x');
push(st,'x');
push(st,'x');
push(st,'x');
push(st,'x');
push(st,'x');
displayStack(st);
pop(st);
return 0;
}
Here:
struct Stack {
int top;
char array[];
};
array can be used as a flexible array member, but you need to malloc with the size of the struct + the number of elements you want to use in the array, i.e.:
data = malloc(sizeof(*data) + nelements);
otherwise the compiler doesn't know how many elements you want to associate to the array

C doesn't put data in arrays or varibles

I'm the beginner in C programming< for now I'm using linux and tried both gcc and clang compilers. However, I'm facing the one problem, sometimes C doesn't put data in the array or variable. For example, there is one of my simple codes, that doesn't work completely:
#include <stdio.h>
#define size 10
struct stack{
int structTop;
int elemNum[size];
};
int create (struct stack s);
int full (struct stack s);
void push (int elem, struct stack s);
void main() {
struct stack s1;
struct stack s2;
struct stack s3;
int a = 545;
create(s1);
push(a, s1);
push(5, s1);
push(a, s1);
push(1, s1);
push(6, s1);
push(4, s1);
push(7, s1);
push(8, s1);
int i = 0;
while (i<4){
printf("%d\n", s1.elemNum[i]);
i++;
}
}
int create (struct stack s){
s.structTop = -1;
return 0;
}
int full(struct stack s){
if(s.structTop == size-1) {
return 1;
}
else {
return 0;
}
}
void push(int elem, struct stack s){
if(full(s)){
printf("Stack is full");
}
else {
s.structTop++;
s.elemNum[s.structTop]=elem;
}
}
As output I'm getting data, wich was inside array from the beginning (zeros or random numbers). Also it was only one of the codes, i have couple of larger ones, that have the same problem. Variables and arrays inside them are working 50/50, sometimes yes, sometimes no, even if declarations and functions are the same. Someone told me, that it could be the matter of compiler, but i tried different ones and also have a friend with the same Kali linux as me facing this problem on a different PC.
You need to pass pointers to the struct, i.e. int create (struct stack *s) instead of int create (struct stack s). The same for push. Otherwise, you pass a copy and in the function, you will alter a copy and not the originally passed object from main.
The thing why it sometimes worked, at least partially, is that when passing objects by value, these values will be put temporarily on a stack; It seems that the same object from main had several time been pushed right on the same position on the stack, such that it seemed as if it was always the same object. But - as you recognised - this really occasional.
The signatures of your methods should look as follows:
int create (struct stack *s);
int full (const struct stack *s);
void push (int elem, struct stack *s);
Note that - since passing now pointers - you have to access the elements of s using -> (and not .), e.g. s->structTop = -1 instead of s.structTop = -1; and that you have to pass the address of a stack (not the stack itself, e.g. push(a, &s1) instead of push(a, s1).
Note further that in int full (const struct stack *s), I declared s as const, as the function does not intend to alter any value of the members of s.
#include <stdio.h>
#define size 10
struct stack{
int structTop;
int elemNum[size];
};
int create (struct stack *s);
int full (const struct stack *s);
void push (int elem, struct stack *s);
int main() {
struct stack s1;
int a = 545;
create(&s1);
push(a, &s1);
push(5, &s1);
push(a, &s1);
push(1, &s1);
push(6, &s1);
push(4, &s1);
push(7, &s1);
push(8, &s1);
int i = 0;
while (i<4){
printf("%d\n", s1.elemNum[i]);
i++;
}
}
int create (struct stack *s){
s->structTop = -1;
return 0;
}
int full(const struct stack *s){
if(s->structTop == size-1) {
return 1;
}
else {
return 0;
}
}
void push(int elem, struct stack *s){
if(full(s)){
printf("Stack is full");
}
else {
s->structTop++;
s->elemNum[s->structTop]=elem;
}
}

Resources