After more than 10 years of having the luxury of using garbage collected languages, I am returning to C99 and obviously I am having difficulties with memory management.
I have a linked list consisting of stack items and a type Stack which points to the address of the first element of this list.
This is my code so far:
#include <stdio.h>
#include <stdlib.h>
typedef struct StackItem
{
int head;
struct StackItem* next;
} StackItem;
typedef StackItem** Stack;
StackItem* makeStackItem (int head)
{
StackItem* a = (StackItem*) malloc (sizeof (StackItem) );
a->head = head;
a->next = (StackItem*) 0;
return a;
}
Stack makeStack ()
{
Stack stack = (Stack) malloc (sizeof (StackItem*) );
*stack = (StackItem*) 0;
return stack;
}
void pushStack (StackItem* item, Stack stack)
{
item->next = *stack;
*stack = item;
}
void freeStack (Stack stack)
{
StackItem* current = *stack;
StackItem* next;
while (current != 0)
{
next = current->next;
free (current);
current = next;
}
free (stack);
}
int main ()
{
Stack stack = makeStack ();
for (int i = 0; i < 10; i++)
pushStack (makeStackItem (i), stack);
printf ("Here be dragons.\n");
freeStack (stack);
return 0;
}
My questions are:
Are the first lines of makeStack and makeStackItem sensible and
necessary?
Is the last line of freeStack sensible and necessary?
Once main returns, have I freed all the memory previously
allocated?
How can I see whether I have memory leaks or not?
Thank you very much in advance.
Are the first lines of makeStack and makeStackItem sensible and necessary? yes except for the casting malloc issue
Is the last line of freeStack sensible and necessary? yes
Once main returns, have I freed all the memory previously allocated? yes
How can I see whether I have memory leaks or not? use valgrind
I would toss the casts of 0 too.
Related
This question already has answers here:
Difference between null pointers and uninitialized pointers?
(5 answers)
Closed 1 year ago.
I am trying to implement stack in C. I am not getting any compilation error but I am getting the return value as 322122547 without any error. What should I do ?
Here is my code
#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 isFull(struct stack * ptr)
{
if (ptr->top == ptr->size - 1)
{
return 1;
}
else
{
return 0;
}
}
int main()
{
struct stack *s;
s->size = 10;
s->top = -1;
s->arr = (int *)malloc(s->size * sizeof(int));
if(isEmpty(s)){
printf("The stack is empty");
}
else{
printf("The stack is not empty");
}
return 0;
}
If I use a struct stack pointer I do not get any output. Should I consider changing the pointer part
Turn on your compiler errors and it will tell you right away what's wrong. For example if I compile your code with gcc -Wall -Werror it says:
error: 's' is used uninitialized [-Werror=uninitialized]
s->size = 10;
| ~~~~~~~~^~~~
Problem origin
struct stack *s; is defining a pointer that is expecting an instance of your structure. Now by default, that expected structure is not initialized and therefore the pointer points to a random location in memory.
You can visualize this error by using gcc -Wall -Werror the compiling and you get:
error: 's' is used uninitialized [-Werror=uninitialized]
s->size = 10;
| ~~~~~~~~^~~~
Since the location the pointer is pointing to is random, you will get random values from your pointer depending on what that memory location contains.
A solution
A way to fix this is to initialize the structure your pointer is expecting to point to in order to allocate this structure. You can do this in two way:
Static allocation: you can create a structure and then point to it using:
struct stack s_static;
struct stack *s = &s_static;
The final code would be:
int main()
{
struct stack s_static;
struct stack *s = &s_static;
s->size = 10;
s->top = -1;
s->arr = (int *)malloc(s->size * sizeof(int));
if(isEmpty(s)){
printf("The stack is empty");
}
else{
printf("The stack is not empty");
}
return 0;
}
Dynamic allocation: you can dynamically allocate your structure in memory by using malloc. You can allocate your stack instance s by doing struct stack* s = (struct stack*) malloc(sizeof(struct stack));. This is a big line. What's happening? struct stack* s tells the compiler this is a pointer that is pointing to a memory location. (struct stack*) is telling the malloc that the new memory location we're about to allocate has type struct stack. Finally, malloc creates some space on the heap for our instance and sizeof(struct stack) simply tells the malloc command how much memory we need to allocate. After putting this line, the code will compile without errors.
BUT WAIT! If you use dynamic allocation, you need to also free the heap once you finish, otherwise the memory location will leak. Therefore, before your return 0, you need to free that memory location. You can do so by using free(s)
The final dynamic allocation approach will look something like this:
int main()
{
struct stack* s = (struct stack*) malloc(sizeof(struct stack));
s->size = 10;
s->top = -1;
s->arr = (int *)malloc(s->size * sizeof(int));
if(isEmpty(s)){
printf("The stack is empty");
}
else{
printf("The stack is not empty");
}
free(s);
return 0;
}
So I'm having a problem with memory leaks in my program. One of my functions free_stack is suppose free all the memory in the stack and the stack should not be used after this function call. My other problem is in my reset_stack function which is suppose to free any memory not in use anymore. The stack can be used after the function call and the function is also suppose to reset the stack to its original contents in *make_stack.My program is not doing this. Here's my code.
struct int_stack *make_stack(int node_capacity){
struct int_stack *stk = malloc(sizeof(struct int_stack));
struct is_node *head = malloc(sizeof(struct is_node));
head->contents = malloc(node_capacity * sizeof(int));
head->next_index = 0;
head->next = NULL;
stk->node_capacity = node_capacity;
stk->head = head;
stk->size = 0;
return stk;
}
void free_stack(struct int_stack *stk) {
while(stk->head->next != NULL) {
free(stk);
}
}
void reset_stack(struct int_stack *stk) {
free_stack(stk);
*make_stack(stk->node_capacity);
}
calling free doesn't do anything to your allocated memory, and also value of pointers you called free on. And also your function *make_stack(stk->node_capacity); returns pointer to the newly allocated stack, use that. stk = *make_stack(stk->node_capacity);.
I want to pass a node by reference to a function and expect the variable in main() to be updated by the function
struct stack
{
int item;
struct stack *link;
};
void push(int item, struct stack *top)
{
/* allocate memory and insert item*/
}
int main(void)
{
struct stack *top;
push(10,top);
printf("%d\n",top->item);
return 0;
}
Here it displays 'segmentation fault', as if top did not get updated at all!
You need to pass the pointer top in main() by reference to the function push(). So give the address of top not its value.
So use
push(10,&top);
instead of
push(10,top);
if the changes made to top in push() are to reflected back in main().
This necessitates the modification of the function prototype. Use
void push(int item,struct stack **top)
instead of
void push(int item,struct stack *top)
And use *top in places where you used top in the push().
There are two options for what you need to do, depending on whether your function allocates the stack or the main() function allocates the stack element.
Option 1 — main() allocates top
void push(int item, struct stack *top)
{
top->link = 0;
top->item = item;
}
int main(void)
{
struct stack top; // Plain structure, not a pointer
push(10, &top); // Pass address of structure to function
printf("%d\n", top.item);
return 0;
}
This doesn't work particularly well in the context of a stack, but can often be the correct way to process structures — the calling code allocates the structure and the called code uses the allocated structure. Here is a dynamic allocation in the calling code, passed to the function to be initialized:
int main(void)
{
struct stack *top = malloc(sizeof(*top));
if (top != 0)
{
push(10, top);
printf("%d\n", top->item);
free(top);
}
return 0;
}
Option 2 — push() allocates top
void push(int item, struct stack **top)
{
struct stack *node = malloc(sizeof(*node));
node->link = *top;
node->item = item;
*top = node;
}
int main(void)
{
struct stack *top = 0; // Initialization is crucial
push(10, &top);
printf("%d\n", top->item);
push(20, &top);
printf("%d %d\n", top->item, top->link->item);
free(top->link);
free(top);
return 0;
}
This code is weird because it uses fixed operations instead of loops, but is otherwise kosher. All the code shown using malloc() has been tested with Valgrind and gets a clean bill of health.
I'm very new to C and I'm trying yet to fully understand it. I implemented a stack
but found trouble when making its destructor and it constructor/init.
Are these well done?
These are the typedefs for the structures used by the stack:
typedef struct Node{
void* cargo;
struct Node* next;
}Node;
typedef struct Stack{
int size;
Node* firstOut;
}Stack;
And these are the functions:
void newStack(Stack* stack){
stack = (Stack*)malloc(sizeof(Stack));
stack->firstOut = NULL;
stack->size = 0;
}
void freeStack(Stack** stack){
empty((*stack));
free((*stack)->top);
(*stack)->size = 0;
free(stack);
}
My question is: are they well done? How would someone with proper experience do it?
newStack should simply return the stack pointer that it allocates. It doesn't need to receive a Stack* as an argument.
stack *newStack() {
Stack *stack = malloc(sizeof(Stack));
if (stack != NULL) { // allocation successful
stack->firstOut = NULL;
stack->size = 0;
}
return stack;
}
and freeStack should receive a stack pointer as argument, it doesn't need double indirection.
void freeStack(Stack *stack) {
empty(stack);
free(stack->firstOut); // This isn't done by empty()?
free(stack);
}
There's no need to set stack->size before freeing, since the memory is going to go away and the value it contains is irrelevant.
For a prelab (meaning it's not for a grade), I'm supposed to implement my first ever stack using linked lists. I wrote it adding only one thing to the stack just as practice, as to why it's so short. Anyway, I have no compile errors, besides it saying that "new" is uninitialized in my create_stack function. This is also where I'm getting a segmentation fault, as it's not printing out my first printf function. I am also guessing that the problem is bigger than just me initializing the stack, but this is my problem's start. Please go easy on me if it's something simple, as, like I said, it's my first time doing stacks, and thanks for your help.
#include <stdio.h>
#include <stdlib.h>
typedef struct node_{
char data;
struct node_ *next;
}node;
typedef struct stack_{
unsigned int size;
node* stack;
}stack;
stack* create_stack();
void push(stack* s, char val);
char top(stack* s);
void pop(stack*s);
int main(void) {
char value, val;
stack* new = create_stack();
printf("Enter a letter: ");
scanf("%c", &value);
push(new, value);
val = top(new);
printf("%c\n", val);
pop(new);
return 0;
}
stack* create_stack(){ //initializes the stack
stack* new;
new->size = 0;
new->stack = NULL;
return new;
}
void push(stack* s, char val) {
node* temp = (node*)malloc(sizeof(node)); //allocates
if ( temp == NULL ) {
printf("Unable to allocate memory\n");
}
else{
temp->next = s->stack;
temp->data = val;
s->stack = temp;
s->size = (s->size) + 1; //bumps the counter for how many elements are in the stack
}
}
void pop(stack* s) {
node* temp;
temp = s->stack;
s->stack = temp->next;
free(temp);
s->size = (s->size) - 1; //subtracts from counter
}
char top(stack* s) {
node* temp = s->stack;
char value = temp->data;
return value;
}
The reason it crashes is that you never allocate any memory when you create the stack. Do stack* new = malloc (sizeof(stack)); in the create_stack function.
For the future you might want to use better variable names. Using for instance using new as the name for the stack isn't that good - it isn't very descriptive plus it's a reserved keyword in several languages, C++ for example.
stack *new creates a local pointer, but it has nothing to point to yet. Since you want the stack to continue to exist after the function completes, you should allocate memory for it using malloc (and eventually free it using free).
So your create_stack function should start with:
stack* new = malloc(sizeof(stack));
An alternative would be to declare the stack as a local variable in your main function, and pass it as an argument into create_stack to initialize it:
stack new;
create_stack(&new);