Adding item to a stack make it crash - c

I am trying to implement on my own (in order to understand it better) the Stack data structure in C language.
Here is what I've got so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stack{
//Data_Strucure: Stack of intgers
int *stack;
int size_of_stack;
int elem_in_stack;
};
struct stack *creat_stack(unsigned int);
int push(struct stack *, int);
int pop(struct stack *);
int empty(struct stack *);
int peek(struct stack *);
int main(int argc, char *argv[]){
int new_elem = 13;
struct stack *new_stack = creat_stack(5);
printf("%d %d\n", new_stack->size_of_stack, new_stack->elem_in_stack);
//Crashes from here
push(new_stack, new_elem);
printf("%d\n", new_stack->stack[new_stack->size_of_stack]);
}
struct stack *creat_stack(unsigned int size){
struct stack tmp;
struct stack *ret_stack = &tmp;
if((ret_stack->stack = malloc(sizeof(int) * size)) == NULL){
fprintf(stderr, "Unable to allocate memory for the Stack.\n");
exit(1);
}
ret_stack->size_of_stack = size;
ret_stack->elem_in_stack = 0;
return ret_stack;
}
int push(struct stack *stack, int nw_elem){
int pos = stack->size_of_stack - stack->elem_in_stack;
if(stack->size_of_stack == 0)
return 1;
stack->stack[pos] = nw_elem;
}
The compiler returns me no error. Though I don't understand why it crashes after push() is called.
Please, if possible, instead of solution code, can you just tell me where the error is? This way I can understand how it effect the whole program and try to solve it on my own (so next time won't happen again).
Thanks is advance for any of your usefull answers.

At least the function creat_stack is incorrect.
struct stack *creat_stack(unsigned int size){
struct stack tmp;
struct stack *ret_stack = &tmp;
//...
return ret_stack;
}
It returns a pointer to the local object tmp that will not be alive after exiting the function. So the returned pointer will be invalid and dereferencing such a pointer invokes undefined behavior.
Instead you could return the object itself from the function. That is the function declaration could look like
struct stack creat_stack(unsigned int size);
And in main you can write
struct stack new_stack = creat_stack(5);
Also the function push does not change the data member elem_in_stack And again it invokes undefined behavior because when elem_in_stack is equal to 0 then the function tries to write to memory outside the dynamically allocated array. That is in this case pos is equal to size_of_stack.
int push(struct stack *stack, int nw_elem){
int pos = stack->size_of_stack - stack->elem_in_stack;
if(stack->size_of_stack == 0)
return 1;
stack->stack[pos] = nw_elem;
}

Related

Problem with my stack implementation in C [duplicate]

This question already has answers here:
Why does call-by-value example not modify input parameter?
(6 answers)
How to modify a struct in a function and return to main?
(2 answers)
Closed 10 months ago.
I'm learning Data Structures and was implementing a stack on C. The code compiles correctly but the stack remains unedited i.e. nothing is being pushed into the stack even after a push operation and it stays empty. I'm not sure where the problem with this code is. Please help me with this. Thanks.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 101
//Define a struct
struct stack{
int A[MAX_SIZE]; //Array of size 101
int top; //Variable that stores the index position of the recently inserted element in the stack.
};
//Function to create a stack, set top to -1 and return it.
struct stack CreateStack(){
struct stack p;
p.top = -1;
return p;
}
//Function to insert a number at the end of the stack.
void Push(int x, struct stack p){
//If the array is full, return an error message.
if (p.top == MAX_SIZE - 1){
printf("Error: Stack Overflow!");
return;
}
//Increment top and set insert x at the last of A.
p.top++;
p.A[p.top] = x;
};
//Function to delete an element from the last in a stack.
void Pop(struct stack p){
//If stack is already empty, print a message.
if (p.top == -1){
printf("Empty Stack!");
return;
}
//Decrement top.
p.top--;
};
//Function to return the top element in the stack.
int Top(struct stack p){
return p.A[p.top];
};
//Function to check if the stack is empty.
int IsEmpty(struct stack p){
return p.top == -1;
};
//Function to display all the elements in the stack.
void Print(struct stack p)
{
printf("Stack: ");
for(int i = 0; i <= p.top; i++){
printf("%d", p.A[i]);
}
printf("\n");
};
int main(){
struct stack mystack = CreateStack(); //Creates a stack called mystack.
Push(22, mystack); //Pushes 22 on the stack.
Print(mystack);// Should display 22.
}
You pass struct stack p by value (copy); instead pass it in via pointer so the modifying functions can change state:
void Push(int x, struct stack *p,) {
if (p->top == MAX_SIZE - 1){
printf("Error: Stack Overflow!");
return;
}
p->A[p->top++] = x;
};
It's a convention to pass the abstract data type (here struct stack *p) as the first argument. Also consider returning a status so caller can tell if the function failed. Finally, it's a good idea to separate i/o (printing error messages) from logic, as it may depend on the context of the caller (console/browser/gui, but also it may not be an error for caller if the stack is full). For example:
struct stack *Push(struct stack *p, int x) {
if (p->top == MAX_SIZE - 1) return NULL;
p->A[p->top++] = x;
return p;
};

I was trying to create a stack data type using array in pointer. But my program is giving segmentation fault

This is the code here. Even after debugging I'm not able to find the problem. The code was working fine if I'm not using the pointer.
#include <stdio.h>
#include <stdlib.h>
struct stack{
int size;
int top;
int *arr;
};
int isEmpty(struct stack *ptr){
if ((*ptr).top == -1){
return 1;
}
else{
return 0;
}
}
int main()
{
struct stack *s;
(*s).size = 80;
(*s).top = -1;
(*s).arr = (int *)malloc((*s).size * sizeof(int));
// Check if stack is empty
if(isEmpty(s)){
printf("The stack is empty");
}
else{
printf("The stack is not empty");
}
return 0;
}
You did not allocate any memory for your struct. You may decalre it on the stack: struct stack s; or allocate memory for it: struct stack *s = (struct stack *)malloc(sizeof(struct stack));.
When you have a pointer to a struct, please use the -> operator to access its members like so s->size.

C - Program crash after free()

I have a program that creates a struct named Stack that holds a pointer to an array of ints and an int that shows the size of this array.
I have functions to:
Initialize the struct with empty values
Push integers to the array (dynamically allocate more memory and write a value to it)
Pop an int from the array
However, when I try to pop the last element by freeing the memory it occupies, my program crashes.
What am I doing wrong here?
Is my process correct?
I realize the problem is probably that I'm trying to free a segment of memory that has not been allocated dynamically, but I just don't see where the issue is exactly.
#include <stdio.h>
#include <stdlib.h>
#include <mem.h>
struct Stack{
int *array;
int size;
};
typedef struct Stack Stack;
void initStack(Stack *stack);
void push(Stack *stack, int value);
int pop(Stack *stack);
int main()
{
Stack firstStack;
initStack(&firstStack);
push(&firstStack, 1222);
pop(&firstStack);
push(&firstStack, 555);
for(int i = 0; i < firstStack.size; ++i){
printf("#%d: %d (%p) ", i , firstStack.array[i], &firstStack.array[i]);
}
return 0;
}
void initStack(Stack *stack){
stack->array = NULL;
stack->size = 0;
}
void push(Stack *stack, int value){
int size = stack->size;
int newSize = size + 1;
stack->array = realloc(stack->array, newSize * sizeof(int));
if(stack->array != NULL){
stack->array[size] = value;
stack->size = stack->size + 1;
}
else{
printf("MALLOC ERROR");
}
}
int pop(Stack *stack){
int lastValue = stack->array[stack->size];
int lastIndex = (stack->size)-1;
int* lastAddress = (stack->array)+lastIndex;
free(lastAddress);
stack->size = (stack->size) - 1 ;
printf("memory free\n");
return lastValue;
}
int* lastAddress = (stack->array)+lastIndex;
free(lastAddress);
is wrong because lastAddress may not be an address allocated via malloc() family by adding lastIndex.
Remove the line
free(lastAddress);
If you want the system to change tha allocated size, you should change the line to
stack->array = realloc(stack->array, ((stack->size) - 1) * sizeof(int));
This is a problem:
int* lastAddress = (stack->array)+lastIndex;
free(lastAddress);
The argument to free must be an address value returned from malloc, calloc, or realloc - you cannot free memory at an arbitrary address, even within a dynamically allocated block.

Local variable might not have been initialized

I'm trying to call queue_t from my main function in order to give queue_t the size which I then intend to print out for test purpose .
Why does it say that my q is not initialized when I did in line 21 ?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct queue_t {
char *name;
int size;
int entries;
double time;
struct packet_t **packets;
int read;
int write;
long lost;
};
struct queue_t *queue_create (char *name, int size) {
int i;
struct queue_t *q;
q->size = size;
q->name = name;
printf("Name of queue: %s", q->name);
printf("Size of queue: %d", q->size);
return (q);
}
int main () {
char *a = "Test";
int size = 80;
queue_create(a, size);
}
struct queue_t *q;
q->size = size;
The pointer q is clearly uninitialized here. And then you use it in q->size. You should assign/initialize a variable before using, ie. q = something;. Using an uninitialized pointer value might be undefined behavior.
You can:
struct queue_t *q = malloc(sizeof(*q));
if (q == NULL) { fprintf(stderr, "ERROR! malloc!\n"); abort(); }
q->size = size;
q is clearly assigned a value here, ie. the result of malloc() call. It allocates the memory for the queue_t on the heap. Remember to free() the pointer so that your program does not leak memory.
You also can allocate the memory for variable on the stack:
struct queue_t q_memory;
struct queue_t *q = &q_memory;
q->size = size;
But note that in this case the memory will be invalid after closing the block it was declared in, ie. after the }! So don't use it, if you want to return it from a function.

Why do I need to use & to pass a pointer to a struct in this stack implementation [duplicate]

This question already has answers here:
What is the reason for using a double pointer when adding a node in a linked list?
(15 answers)
Closed 7 years ago.
In the following program I need to pass an argument to a function using the &-operator although I expect it to be a pointer and the function is expecting a pointer. Why do I need to do this?
The program implements a simple stack using linked lists and incomplete types in C. Here are the three necessary files:
stack.h
#ifndef STACK_H
#define STACK_H
#include <stdbool.h>
struct Stack {
int number;
struct Stack *next;
};
/*
* We declare a pointer to a Stack structure thereby making use of incomplete
* types. Clients that pull in stack.h will be able to declare variables of type
* pstack which are pointers to Stack structures. */
typedef struct Stack *pstack;
bool is_empty(pstack *s);
void make_empty(pstack *s);
void push(pstack *s, int new_num);
int pop(pstack *s);
#endif /* STACK_H */
stack.c
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
bool is_empty(pstack *s)
{
return !s;
}
void make_empty(pstack *s)
{
if (!is_empty(s))
pop(s);
}
int pop(pstack *s)
{
struct Stack *tmp;
int i;
if (is_empty(s)) {
exit(EXIT_FAILURE);
}
tmp = *s;
i = (*s)->number;
*s = (*s)->next;
free(tmp);
return i;
}
void push(pstack *s, int new_num)
{
struct Stack *new_node = malloc(sizeof(struct Stack));
if (!new_node) {
exit(EXIT_FAILURE);
}
new_node->number = new_num;
new_node->next = *s;
*s = new_node;
}
stackclient.c
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
int main(void)
{
pstack s1;
int n;
push(&s1, 1);
push(&s1, 2);
n = pop(&s1);
printf("Popped %d from s1\n", n);
n = pop(&s1);
printf("Popped %d from s1\n", n);
exit(EXIT_SUCCESS);
}
Again, I thought that by using
typedef struct Stack *pstack;
and later on in main()
pstack s1;
I'm declaring a pointer to the linked list Stack and hence it would be fine to simply pass s1 to say push() by just using
push(s1, 1);
but I actually need to use
push (&s1, 1);
Why?
Your functions are all declared to take pstack* as an argument, which is actually a pointer to a pointer to a Stack struct. Just use pstack. You'll also need to replace the instances of (*s) with just s in the implementations of those functions.
Edit: As was pointed out in the comments, you actually write to (*s) in the function implementations and rely on this behavior for correctness, so you need to keep the argument as pstack*. Conceptually, this is because the stack variable (s1) is literally the top of the stack itself, and so must be modified by push and pop.
You need to use pstack *s ( pointer to pstack ) in void push(pstack *s, int new_num), according to your implementation code,
if to use pstack s( pstack ), the new_node will not be returned correctly.
Two possible ways to insert a Node in push():
if insert to head, it should be *s = new_node
if insert to tail, it could be s->next = new_node
Back to the code, if to use push(s1, 1); such as,
//If only use pstack s, the new_node can not be pushed.
void push(pstack s, int new_num) //it is a wrong implementation for demo
{
struct Stack *new_node = malloc(sizeof(struct Stack));
if (!new_node) {
exit(EXIT_FAILURE);
}
new_node->number = new_num;
new_node->next = s;
s = new_node;// WRONG! here, the new_node cannot be kept by s
// two typical node insert ways:
// 1)if insert to head, it should be *s = new_node
// 2)if insert to tail, it could be s->next = new_node
//Now, Your code applied the #1 way, so need *s
}
So, it should be inputed pstack *s, and call with push (&s1, 1);
void push(pstack *s, int new_num)//it is the correct version the same as your post
{
struct Stack *new_node = malloc(sizeof(struct Stack));
if (!new_node) {
exit(EXIT_FAILURE);
}
new_node->number = new_num;
new_node->next = *s;
*s = new_node;//here, the new_node could be kept by *s
}

Resources