Local variable might not have been initialized - c

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.

Related

Why is this code not working? The code should print the elements but it just runs and then exits without dispalying the elements

#include <stdio.h>
#include <stdlib.h>
struct queue
{
int front;
int rear;
int size;
int *arr;
};
void enqueue(struct queue *q, int value)
{
if(q->rear!=q->size-1)
{
printf("Entry\n");
q->rear++;
q->arr[q->rear] = value;
}
}
int main()
{
struct queue *q; /*struct queue *q=(struct queue *)malloc(sizeof(struct queue));*/
q->front = -1;
q->rear = -1;
q->size = 10;
q->arr = (int *)malloc((q->size) * sizeof(int));
enqueue(q,14);
enqueue(q,7);
enqueue(q,5);
enqueue(q,4);
enqueue(q,3);
enqueue(q,2);
for(int i=0;i<q->rear;i++){
printf("%d ",q->arr[i]);
}
return 0;
}
I was expecting the elements of the queue to be printed.
When the line
"struct queue *q;"
is replaced with this "
*struct queue *q=(struct queue *)malloc(sizeof(struct queue));"
it works, what is the reason?
The segmentation-fault occurs because you have not allocated memory for q.
What you have written as:
struct queue *q;
Is a pointer, that is, a variable that stores the memory address of another variable. You have created something that can point to memory but have not provided it any memory to point to.
malloc provides you memory from the heap, which is a typical way of having memory allocated and is why the commented code works.
An alternative would be to use memory on the stack:
struct queue q;
q.front = -1;
q.rear = -1;
q.size = 10;
q.arr = (int *)malloc((q.size) * sizeof(int));
And then using it as:
enqueue(&q,14);
struct queue *q;
q = (struct queue *)malloc(sizeof(struct queue)); /*In order to write data, you first need to allocated to memory for it. and if you do it like q->arr you will allocated to memory for the second step so (think of this list as an array if you do q->arr you will allocated for arr[1] instead of arr[0])*/
q->front = -1;
q->rear = -1;
q->size = 10;
/but this will only allocate the first part in memory (only for arr[0])/
/*so you can write code in void enqueue(struct queue *q, int value) to allocated a new memory in each operation */
/I understand that you are trying to determine the memory in one go by assigning size to 10 , but you can not do like this.because the part you allocate here is just a value you put in arr[0], you can't use it as the size of your list./

Adding item to a stack make it crash

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;
}

Error in stack with linked list implementation

I'm trying to implement stack using linked list implementation. Its giving me "Segmentation Error". Please help me finding the error. This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
struct NODE {
char word;
struct NODE *next;
};
struct STACK {
struct NODE *head;
int size;
};
void pushStack(struct STACK *stack, char s);
void makeStack(struct STACK *stack, char *s);
void printStack(struct STACK *stack);
int main(){
char *s;
fgets(s,100,stdin);
struct STACK stack;
stack.head = NULL;
makeStack(&stack,s);
printStack(&stack);
return 0;
}
void pushStack(struct STACK *stack, char s){
struct NODE temp;
temp.word = s;
temp.next = stack->head;
stack->head = &temp;
}
void makeStack(struct STACK *stack, char *s){
char temp[MAX];
strcpy(temp,s);
for(int i=0; i<MAX; i++){
if(temp[i]=='\0') break;
pushStack(stack,temp[i]);
}
}
void printStack(struct STACK *stack){
struct NODE *trav = stack->head;
while (trav != NULL){
printf("%c", trav->word);
trav = trav->next;
}
}
MAX=100 is the limit I'm taking for string input. I haven't also added increasing the size because I'm just ignoring the increment of size for now. Before I could perfect the implementation
In main the s pointer is not initialized and it points nowhere.
int main(){
char *s; // <<< this is wrong, you want 'char s[100]' instead
fgets(s,100,stdin);
...
However the safest option is this:
int main(){
char s[100]; // declare array of 100 chars
fgets(s, sizeof(s), stdin); // sizeof(s) is the actual size of s (100 here)
...
This is wrong too: you store the pointer to the local variable temp, but that variables ceases to exist once you return from the pushStask function.
void pushStack(struct STACK* stack, char s) {
struct NODE temp;
temp.word = s;
temp.next = stack->head;
stack->head = &temp;
}
Instead you need to create a new struct NODE like this:
void pushStack(struct STACK* stack, char s) {
struct NODE* temp = malloc(sizeof *temp);
temp->word = s;
temp->next = stack->head;
stack->head = temp;
}
Instead of malloc(sizeof *temp) you could write sizeof(struct NODE), it's the same, but it's less fool proof because you could mistakenly write sizeof(struct STACK) which would compile fine, but the size of the allocated memory would be wrong.
Another problem: you don't assign the size field of the struct STACK, this is not a problem now, but it might become a problem later.
There are several drawbacks in your implementation of a stack.
The first one is that you are using a pointer with an indeterminate value to read a string
char *s;
fgets(s,100,stdin);
So the call of fgets invokes undefined behavior.
Moreover there is used a magic number 100.
You need to allocate a character array and use it to read a string.
#define MAX 100
//...
char s[MAX];
fgets( s, MAX, stdin );
Pay attention to that the name word for an object of the type char is confusing
struct NODE {
char word;
struct NODE *next;
};
You could define the structure like for example
struct NODE {
char c;
struct NODE *next;
};
or
struct NODE {
char item;
struct NODE *next;
};
Instead of separating the declaration and the initialization as you did
struct STACK stack;
stack.head = NULL;
forgetting to initialize the data member size (that by the way should have an unsigned integer type as for example size_t) you could just write for example
struct STACK stack = { NULL, 0 };
or
struct STACK stack = { .head = NULL, .size = 0 };
In the declaration of the function makeStack the second parameter should have the qualifier const because the passed string is not being changed within the function. And as a memory allocation in general can fail the function should report whether all characters of the string were pushed successfully. So the function declaration should look like
int makeStack( struct STACK *stack, const char *s );
It does not make a sense to declare a local array temp within the function
void makeStack(struct STACK *stack, char *s){
char temp[MAX];
//...
using the index variable i is redundant. Also the function fgets can append the new line character '\n' to the input string that you should not push on stack.
The function can be defined the following way
int makeStack( struct STACK *stack, const char *s )
{
int success = 1;
for ( ; *s && success; ++s )
{
if ( *s != '\n' )
{
success = pushStack( stack, *s );
}
}
return success;
}
Another approach is to remove the new line character from the input string before passing it to the function makeStack.
For example
s[ strcspn( s, "\n" ) ] = '\0';
makeStack( &stack, s );
If it is the user that is responsible whether to push the new line character on stack or not then the function makeStack can be simplified
int makeStack( struct STACK *stack, const char *s )
{
int success = 1;
for ( ; *s && success; ++s )
{
success = pushStack( stack, *s );
}
return success;
}
Correspondingly the function pushStack also should be redefined.
For starters it shall dynamically allocate a new node. Otherwise you will try to add nodes that are local to the function and will not be alive after exiting the function that again results in undefined behavior.
The function pushStack can be defined the following way.
int pushStack( struct STACK *stack, char c )
{
struct NODE *temp = malloc( sizeof( struct NODE ) );
int success = temp != NULL;
if ( success )
{
temp->word = c;
temp->next = stack->head;
stack->head = temp;
++stack->size;
}
return success;
}
The parameter of the function printStack should have the qualifier const because the stack itself within the function is not being changed.
The function can be defined at least the following way
void printStack( const struct STACK *stack )
{
for ( const struct NODE *trav = stack->head; trav != NULL; trav = trav->next )
{
printf( "%c", trav->word );
}
}

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.

Queue Dynamic Array

i am studying queue in c and trying to make basic queue program. But couldn't manage to allocate memory for my array. Here is my queue declaration and my createqueue function. After allocating memory space for myQueue, i should allocate for array aswell but i dont know how. Should i just type myQueue->array =(myQueue)malloc(sizeof(myQueue)); will it work ?
struct QueueRecord
{
int capacity;
int front;
int rear;
int size;
int *array;
};
typedef struct QueueRecord *Queue;
Queue CreateQueue(int maxElements)
{
Queue myQueue;
if (maxElements<MIN_QUEUE_SIZE)
{
printf("Queue is too small\n");
return;
}
myQueue = (Queue*)malloc(sizeof(Queue));
if (myQueue == NULL)
printf("out of memmory space");
myQueue->array =(myQueue)malloc(sizeof(myQueue));
myQueue->capacity=maxElements;
MakeEmptyQueue(myQueue);
return myQueue;
}
i should allocate for array aswell but i dont know how
because of the line
myQueue->capacity=maxElements;
the logic is to have
myQueue->array = malloc(sizeof(int) * maxElements);
Should i just type myQueue->array =(myQueue)malloc(sizeof(myQueue)); will it work ?
only in case sizeof(myQueue) is greater than sizeof(int) * maxElements, but you only check maxElements not too small, when maxElements is enough large the behavior is undefined (typically when maxElements is greater than 6 when the size of a pointer is the double of the size of an int).
Out of that :
It is a bad idea to have a typedef defining a pointer, better to have the pointers explicit in the code to see them
the first return; must be return NULL;
knowing myQueue is NULL do not dereference it after, you can directly return NULL after the printf
you check the first malloc does not return NULL, do also for the second, typically in the same if
For instance :
struct QueueRecord
{
int capacity;
int front;
int rear;
int size;
int *array;
};
typedef struct QueueRecord Queue;
void MakeEmptyQueue(Queue *);
Queue * CreateQueue(int maxElements)
{
Queue * myQueue;
if (maxElements < MIN_QUEUE_SIZE)
{
printf("Queue/maxElements is too small\n");
return NULL;
}
if (((myQueue = malloc(sizeof(Queue))) == NULL) ||
((myQueue->array = malloc(sizeof(int) * maxElements)) == NULL))
{
printf("out of memory space\n");
free(myQueue); /* to avoid memory leak, no problem if myQueue is NULL */
return NULL;
}
myQueue->capacity = maxElements;
MakeEmptyQueue(myQueue);
return myQueue;
}

Resources