C- Crashes while or after free() in remove function - c

i Wrote a queue in c
and in the function remove when i tring to free the memory of the node the program crashes.
this is the code of the function remove:
int RemoveFromQueue(Queue a)
{
int r=0;
printf("test0\n");
if(a->First!=NULL)
{
printf("test1\n");
a->Length=a->Length-1;
r=a->First->DATA;
NodeQ tmp=a->First;
printf("test2\n");
if(tmp==a->Last)
{
a->Last=NULL;
}
printf("test3\n");
a->First=a->First->next_Node;
printf("test4\n");
free(tmp);
printf("test5\n");
}
else
{
return NULL;
}
return r;
}
the code of queue:
struct NodeQ_s{
int DATA;
struct NodeQ_s *next_Node;
};
struct Queue_s{
int Length;
NodeQ First;
NodeQ Last;
};
.h file:
typedef struct NodeQ_s *NodeQ;
typedef struct Queue_s *Queue;
insert function:
void InsertToQueue(Queue a,int b)
{
if(a->First==NULL)
{
a->Length=1;
a->First=malloc(sizeof(*(a->First)));
a->First->DATA=b;
a->First->next_Node=NULL;
}
else
{
a->Length=a->Length+1;
NodeQ tmp=malloc(sizeof((*tmp)));
tmp->DATA=b;
if(a->Last==NULL)
{
a->Last=tmp;
a->First->next_Node=a->Last;
}
else
{
a->Last->next_Node=tmp;
a->Last=a->Last->next_Node;
a->Last->next_Node=NULL;
}
}
}
can you tell me what i did wrong or why it crashes?

It is crashing because you're trying to free dynamic memory that doesn't even exist!
free takes a pointer to a memory location that it's supposed to deallocate, and you're passing it a NodeQ object. You see where the problem lies ?
If a->First is a malloc'd pointer you want to free then I guess that you want to point to it, not create a copy of it like you did. Like this:
NodeQ *tmp = a->First;
Then you can free it.
OfCourse if a->First isn't a malloc'd pointer then you don't have call free.
Edit
After seeing your struct definition, First isn't even a pointer! You can't call malloc for it.
Or you can get what's stored in there using the dereferencing operator like this: *malloc and when you're freeing it, get its address, like this: free(&a->First)

Related

passing top pointer of stack as argument

My problem is based on pointers, I want to know how can i pass top of stack in function printStack() so that i can access all nodes of stack.I am storing elements in array and same time pushing into stack.
here in this code when i execute it does not print anything.
here my code
#include<stdio.h>
struct stack
{
int data;
struct stack *next;
};
typedef struct stack s;
s *top=NULL,*neu;
//push data into stack
void push(int data)
{
neu = (s *)malloc(sizeof(s));
neu->data= data;
neu->next = NULL;
if(!top)
{
neu=top;
}
else
{
neu->next = top;
top = neu;
}
}
//pop data and move top to top->next
void pop()
{
s *temp = top;
top = top->next;
free(top);
}
//print data present in stack
void printStack(s *top)
{
while(top)
{
printf("%d ",top->data);
pop();
}
}
int main()
{
int i=0,A[3],d;
for(i=0;i<3;i++)
{
scanf("%d",&A[i]);
push(A[i]);
}
printStack(top);
return 0;
}
So there are 3 problems:-
You are freeing top rather than temp in pop().
You are changing to the local variable passed in printStack.
Simply call this printSack(); having function signature void printStack().
Also when creating the nodes
if(!top)
{
neu=top;
^^^^
}
This will be top=neu;
Some things that you should learn to do:-
Use debugger. Learn how to use it.
Don't cast the return value of malloc.
Check the return value of malloc and scanf.
You have used too many global variables - code that involves lots of global variables are tend to be difficult to debug. You could easily avoid it here.
For example:-
if( scanf("%d",&A[i])!= 1){
fprintf(stderr,"Error in input");
exit(EXIT_FAILURE);
}
In case of malloc
neu = malloc(sizeof(s));
if(neu == NULL ){
perror("Malloc failed");
exit(EXIT_FAILURE);
}
The main thing is - your code is doing nothing basically. It is even useless to create those methods which are so closely couped with each other with data. We use functions so that code becomes modular and each of the function should be reusable.( Atleast to some extent). Here you have missed that part.
You have a simple error here:
void pop()
{
s *temp = top;
top = top->next;
free(top);
}
Rather than freeing Top, you likely meant to free(temp);
Additionally, consider developing good habits early. Don't cast the return of malloc() in C. Also, don't assume that malloc() worked; check to see if it returns something other than NULL.

dynamic stack with static array C

I have been doing excercises from a book. And I am stuck on the meaning of this qustion. Assuming that you store integer values on the stac and that using a static array to store data provide a createStack() deleteStack(stack) methods.
My interpretation is
typedef struct {
int values;
char data[50];
} StackData;
typedef struct n {
StackData d; // store some data in node
struct n *successor; // store successor of node
// as typedef is not yet completed
// name StackNode cannot be used
} SatckNode;
typedef struct {
StackNode *head;
StackNode *current;
} Stacklist;
I know these arent the methods. But i want to know if I am going about it the right way
If you're using a static array for the values, then you don't technically need createStack() and deleteStack() functions, because you can just create a struct stack or whatever on the stack (pun intended) and you're done.
If you do want to, though, (and you might legitimately want to, e.g. to avoid having to explicitly initialize top, or to hide the implementation behind an opaque type, or to be able to return one from a function without copying a potentially large array) this'll do it:
#include <stdio.h>
#include <stdlib.h>
#define STACKSIZE 50
typedef struct stack * Stack;
struct stack {
size_t top;
int values[STACKSIZE];
};
Stack createStack(void)
{
Stack new_stack = malloc(sizeof *new_stack);
if ( !new_stack ) {
perror("couldn't allocate memory");
exit(EXIT_FAILURE);
}
new_stack->top = 0;
return new_stack;
}
void deleteStack(Stack stack)
{
free(stack);
}
void push(Stack stack, const int n)
{
if ( stack->top < STACKSIZE ) {
stack->values[stack->top++] = n;
}
else {
fprintf(stderr, "Stack full - exiting.\n");
exit(EXIT_FAILURE);
}
}
int pop(Stack stack)
{
if ( stack->top > 0 ) {
return stack->values[--stack->top];
}
else {
fprintf(stderr, "Stack empty - exiting.\n");
exit(EXIT_FAILURE);
}
}
int main(void)
{
Stack mystack = createStack();
push(mystack, 3);
push(mystack, 1);
push(mystack, 4);
push(mystack, 1);
push(mystack, 5);
for ( size_t i = 0; i < 5; ++i ) {
printf("Popped %d from stack.\n", pop(mystack));
}
deleteStack(mystack);
return 0;
}
Right now you seem to want a stack with values in a static array, but then you start defining structs for nodes and lists, as if you want a linked list implementation. The two implementations are obviously pretty different.
I think you're on the right way - just a couple of comments.
In Stacklist, I don't get why you have pointers to two of the nodes in the stack.
Usually, stacks only keep a reference to the item on the top of the stack.
In addition, they either keep a counter of how big is the stack, or a pointer to the node on the bottom of the stack (which is what you probably mean by head, and reference the head node by current?).
And don't forget to initialize everything whenever you create any of those structures :P usually ends up in endless hours of headache.
Keep up the good work.

my callback struct won't work

I have this code:
/* ... headers ... */
struct my_callback_struct {
int data;
int (*callback_func)(struct my_callback_struct *p, int data);
};
int reg(struct my_callback_struct *p, int data)
{
return 1;
}
void init(struct my_callback_struct *p)
{
p->callback_func = ®
}
int main ()
{
struct my_callback_struct *p;
init(p);
printf("%d", p->callback_func(p,12));
return 0;
}
so, basically I try to map p->callback_func with the function "reg". But when i compile it it says no errors but a segmention fault or something. I put a return of 1 just to check if it works...
What am i doing wrong?
You simply haven't allocated memory for your struct instance. Try something like
struct my_callback_struct s;
init(&s);
printf("%d", s.callback_func(p,12));
Or call malloc for your p before calling init.
You need to allocate your callback struct. The code as written is only a pointer to it. Two opens are:
struct my_callback_struct p; // Just "p", not "*p" which is a pointer
This allocates the struct on the stack. Its memory will no longer be allocated when the enclosing function returns. If you want it to have a longer lifetime you would most commonly use malloc() to dynamically allocate it:
struct my_callback_struct *p = (my_callback_struct*)malloc( sizeof( my_callback_struct ) );
if ( p == NULL ){
return -1; // Indicate failure to allocate
}

Segmentation fault (core dumped) while running the program

#include<stdio.h>
#include<string.h>
#include<malloc.h>
//#include<conio.h>
struct list
{
char *value;
struct list *link;
};
struct list *arr[12];int val;
int hf(char *item)
{
int sum,i=0;
while(item[i]!='\0')
{
sum+=item[i];
i++;
}
return sum%12;
}
void insert(struct list ** arr,char *item,int val)
{
struct list *temp,*r;
r=*arr;
temp=(struct list *)malloc(sizeof(struct list));
strcpy((temp->value),item);
if(strcmp((r->value),NULL))
{
strcpy((r->value),(temp->value));
(r->link)=NULL;
}
else
{
while(r->link!=NULL)
r=r->link;
r->link=temp;
r=r->link;
strcpy((r->value),(temp->value));
r->link=NULL;
}
*arr=r;
}
void main()
{
struct list *li[12];int i=0;
for(i=0;i<12;i++)
{
li[i]=NULL;
}
char *item;int ret;
strcpy(item,"Steve");
ret=hf(item);
insert(&li[ret],item,ret);
strcpy(item,"raj");
ret=hf(item);
insert(&li[ret],item,ret);
strcpy(item,"Notes");
ret=hf(item);
insert(&li[ret],item,ret);
}
The above program is to implement array of linked list and im trying to insert string
as the value. When i am trying to run the program, there are no errors but it tells segmentation fault(core dumped)
so please explain the reason
The code
char *item;int ret;
strcpy(item,"Steve");
tries to copy the string literal "Steve" to an uninitialised pointer. You need to allocate memory for item. The easiest way of doing this is to hard-code a suitably sized stack buffer
char item[50];
You also have a similar problem inside insert. You could solve this in the same way
struct list
{
char value[50];
struct list *link;
};
or you could dynamically allocate the correct size of buffer inside insert
temp->value = malloc(strlen(item) + 1);
if (temp->value == NULL) {
/* handle oom error */
}
strcpy(temp->value, item);
In this latter approach, make sure to free(node->value) when you free that list node. Note also that freeing of all dynamically allocated memory is currently missing from your program, meaning that you leak all memory allocated using malloc.
There is one more bug in your code - insert assumes that arr is a pointer to a valid list* but it is always NULL. You need to update either main or the assumption in insert here.
change the following
In insert() function change the if loop
if(r==NULL){
r = temp;
}
Change the structure. change the size of the structure for your need
struct list
{
char value[25];
struct list *link;
};
Change the variable item to
char item[25];
EDIT :
There is no need to typecast the output of malloc

Errors in the C code

I have written the following code for my project. The code is scattered across various files and quite long so i am posting the minimal code.
#include<stdio.h>
#include<stdbool.h>
struct TwoPoint
{
int width;
int value;
};
struct Module
{
int categ;
void *ptr;
};
struct Rect
{
struct TwoPoint val;
struct TwoPoint val_new;
bool is_changed;
};
struct S
{
int numInstances;
struct Module instances[20];
struct Rect RectList[40];
int numRect;
}s1;
struct Test
{
int categ;
struct Rect state;
};
struct TwoPoint initPVal(int v,int w)
{
struct TwoPoint temp;
temp.value=v;
temp.width=w;
return temp;
}
int getValue(struct TwoPoint *b)
{
return (b->value);
}
struct TwoPoint get(struct Rect *r)
{
return (r->val);
}
void initialize()
{
s1.numInstances=0;
s1.numRect=0;
}
void addRect(struct Rect *r)
{
if(s1.numRect<40)
{
s1.RectList[s1.numRect].val=r->val;
s1.RectList[s1.numRect].val_new=r->val_new;
s1.RectList[s1.numRect].is_changed=r->is_changed;
s1.numRect++;
}
}
struct Rect initRect(struct TwoPoint initval)
{
struct Rect temp;
struct TwoPoint tempP;
tempP=initPVal(0,0);
temp.val=initval;
temp.val_new=tempP;
temp.is_changed=false;
addRect(&temp);
return temp;
}
void copy(struct Rect *r)
{
if(r->is_changed)
{
r->val= r->val_new;
r->is_changed=false;
}
}
void copyRect()
{
int i=0;
for(i=0;i<s1.numRect;i++)
{
copy(&s1.RectList[i]);
}
}
void setInstance(struct Module *m)
{
s1.instances[s1.numInstances].categ=m->categ;
s1.instances[s1.numInstances].ptr=m->ptr;
s1.numInstances++;
if (s1.numInstances >= 20)
{
printf("Too many instances");
}
}
void setModule(struct Test *t)
{
struct Module m;
m.categ=t->categ;
m.ptr=&t;
setInstance(&m);
}
void init(struct Test *t)
{
t->categ=2;
struct Rect tr;
struct TwoPoint tb1=initPVal(0,5);
tr=initRect(tb1);
t->state=tr;
}
void actions(struct Test *t)
{
struct TwoPoint tb=get(&t->state);
int y=getValue(&tb);
printf("%d\n",y);
unsigned int x=getValue(&tb);
printf("%u\n",x);
switch(y)
{
....
}
}
void initS()
{
init(s1.instances[0].ptr);
}
void act()
{
actions(s1.instances[0].ptr);
}
void setup()
{
struct Test t;
initialize();
init(&t);
setModule(&t);
}
void run()
{
initS();
act();
copyRect();
}
int main()
{
printf("foo\n");
setup();
printf("bar\n");
run();
return 0;
}
There are two errors:
The init() function when called through initS() function leads to Stack Overdumped error whereas it worked fine while i called it in setup(). I think Call is correct as action() function is being executed.
The second problem is in actions() function. When i am calculating the value of y to be used as switch condition instead of the value being 0,1,2 or 3 it is some memory address which i found by printing it while trying to debug.
The problem is:
void setup()
{
struct Test t;
initialize();
init(&t);
setModule(&t);
}
A Test structure is allocated as a local stack variable and then the address of it assigned to some variable which is accessed later. The next time this variable is accessed is in (init):
void init(struct Test *t)
{
t->categ=2;
struct Rect tr;
struct TwoPoint tb1=initPVal(0,5);
tr=initRect(tb1);
t->state = tr;
}
At this point the pointer points to a variable that has fallen out of scope, resulting in undefined behaviour. What actually happens is that the stack gets smashed because of the structure assignment which is attempted. This is why it's also difficult to get a backtrace.
One solution is to allocate the memory with malloc like so:
void setup()
{
struct Test * t = malloc(sizeof (struct Test));
initialize();
init(t);
setModule(t);
}
Another problem existed, namely a semantic bug in setModule:
void setModule(struct Test *t)
{
struct Module m;
m.categ=t->categ;
m.ptr=&t;
setInstance(&m);
}
m.ptr=&t should actually be m.ptr = t. The assignment of a pointer to a Test structure was intended. Instead, what happened was that the address of a stack variable holding a pointer to a Test structure (double pointer to a Test structure) was assigned.
I'm assuming that where you show run() calling actions(), it is actually calling act(), since the former function requires a parameter.
In setModule(), you have
m.ptr=&t;
where t is already a pointer to struct Test. So what you have stored in m.ptr is a pointer to a pointer to a struct. In act(), you pass this stored pointer to actions(), which is expecting a pointer to a struct, not a pointer to a pointer to a struct. So when the function dereferences the pointer and treats the result as a struct Test, it's getting who-knows-what.
Most likely, you want to simply change the line in setModule() to
m.ptr=t;
since t is already a pointer. But perhaps there is some reason you really want to have a pointer to a pointer, in which case you need to change the code that uses the pointer to use it properly. A problem here is that the compiler can't help you ensure type safety since you're storing the pointer as void * and implicitly converting it to other types.
As a side note, you seem to be using the & operator a lot more than I think is usual. It seems to me that your functions that are read-only, e.g. getValue(), should simply take a struct parameter, not a pointer to a struct, and then you would not need to obtain the addresses of variables so much. But perhaps this is a matter of taste.

Resources