my callback struct won't work - c

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
}

Related

Initializing struct within a function then storing its address

Hi I have a struct like this
struct small_struct {
int a;
int b;
}
struct big_struct {
struct *small_struct child;
}
I want to pass the pointer of big_struct as a parameter into a function in which child is initialized.
static int my_function(struct big_struct* s) {
if (certain_condition)
s->child = &(struct small_struct) {
.a = 1;
.b = 2;
}
}
However, when I do this and my_function is finished, the fields in s->child are often changed outside of the my_function. Would there be a way to keep a and b values as it was initialized inside my_function?
Thank you!
The problem is here:
s->child = &(struct small_struct) {
.a = 1;
.b = 2;
}
This creates the struct in the stack memory of the function, then assigns the s->child pointer to that memory. As soon as the function returns, that memory is no longer allocated to your struct. What you need to do is allocate heap memory for the structure, using malloc, which will stay allocated until it is free'd with a call to free:
static int my_function(struct big_struct* s) {
if (certain_condition)
{
//Allocate *heap* memory for the pointer
//This must be freed later!
//e.g free(s.child);
s->child = malloc(sizeof(struct small_struct));
s->child->a = 1;
s->child->b = 2;
}
Alternatively, depending on what you are trying to do, don't make child a pointer, that way the memory is already allocated in the instance of big_struct e.g.:
struct big_struct
{
struct small_struct child; //Note: not a pointer
};
static int my_function(struct big_struct* s) {
if (certain_condition)
{
//Memory for child member is already allocated
s->child.a = 1;
s->child.b = 2;
}
}

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.

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

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)

Passing Struct members in Functions

I want to pass struct members in function . I don't mean something like that:
struct smth
{
int n;
};
void funct(struct smth s);
I want these structs
struct student {
char name[50];
int semester;
};
struct prof {
char name[50];
char course[50];
};
struct student_or_prof {
int flag;
int size;
int head;
union {
struct student student;
struct prof prof;
}
}exp1;
struct student_or_prof *stack;
struct student_or_prof exp2;
To pass their members in a fucntion with variables not struct variables
int pop(int head,int n)
{
if(head==n)
return 1;
else head++;
}
Because i don't want to use the function for structs only. Is it possible?
EDIT I want the numbers also to change , not return , something like pointer.
EDIT_2 Also i know that this pop(exp1.head,n) it works, but i want also the exp1.head to change after the end of the function pop.
Use pointers. pass poniter to exp1.head and manipulate it by dereferencing it in function as,
int pop(int * head,int n)
{
if(*head==n)
return 1;
else (*head)++;
}
call function as,
pop(&exp1.head,n);
First things first, you are missing a semicolon, after the union definition inside the struct student_or_prof.
As per your edit #2, you should be passing the address of the variable, taking it as a pointer to a variable by the function, and then editing/incrementing the content of the address (the variable that pointer points to). Like the following:
#include <stdio.h>
struct student_or_prof {
int head;
} exp1;
int pop( int * head, int n ) {
if ( *head == n )
return 1;
else (*head)++;
}
int main( ){
int returnval;
exp1.head = 5;
returnval = pop( &exp1.head, 10 );
printf( "%d", exp1.head );
getchar( );
return 0;
}
This will print a 6. Here, I am passing the address of the exp1.head, so that the function pop can refer to the actual exp1.head you have in your hands. Otherwise, the pop will be only informed about the value that exp1.head had, copy that value into its own head variable, play around with that.
And also, it would be sensible to return some int from the pop in any case. Right now it returns a value only when *head == n is satisfied, and returns something that wouldn't make sense. I don't think you'd want that, so:
...
else {
(*head)++;
return 0;
}
...
Would be better.
If you don't like the parenthesis around the *head, then you may want to use ... += 1; instead of a postfix increment, which has less precedence over the dereferencing operator *.

free the space allocated in c with malloc

I have a question about this code:
typedef struct pop {
unsigned long int *np; // matrix
unsigned long int f;
long double fp;
unsigned long int *R; // matrix
unsigned long int *C; // matrix
unsigned long int Dp;
unsigned long int Ds;
unsigned long int count;
struct popolazione *ptrTempLst; // pointer
struct popolazione *leftTree; // left tree pointer
struct popolazione *rightTree; // right tree pointer
} Node;
When I free space allocated for this struct, prior have I to free pointer to matrix inside struct?
For example,
Node *ptr=(Node *) malloc(sizeOf(Node));
ptr->np=(unsigned long int *)malloc(10*sizeOf(unsigned long int));
/*code code code*/
// is necessary: free(ptr->np);
free(ptr);
Thanks in advance
Yes.
Every call to malloc must have a matching call to free.
That is correct.
To help avoid shooting yourself in the foot, you might consider the following practices:
Always free all malloc/calloc'ed memory with free()
Afterwards, set the pointer to NULL
Use a dedicated cleanup/destroy function to ensure consistent memory cleanup
The following function would be a good way to make sure you always cleanup a structure properly, avoid memory leaks, and avoid accidentally freeing already-freed memory and causing a segmentation fault:
int destroyNode(Node* myNode) {
if(!myNode) {
printf("Invalid pointer! Exiting");
return (-1);
}
// Clear out memory
if(np) {
free(np);
np = NULL;
}
if(R) {
free(R);
R = NULL;
}
if(C) {
free(C);
C = NULL;
}
if(ptrTempLst) {
free(ptrTempLst);
ptrTempLst = NULL;
}
if(leftTree) {
free(leftTree);
leftTree = NULL;
}
if(rightTree) {
free(rightTree);
rightTree = NULL;
}
free(myNode);
}
eg:
int main(void) {
Node *tempNode = calloc((size_t)1,sizeof(Node));
// Alloc the member nodes, etc, do some code
// Ready to clean up and exit program
destroyNode(tempNode);
tempNode = NULL;
return 0;
}
Good luck!

Resources