Home > OS >  Free dynamically allocate struct in C by typecasting
Free dynamically allocate struct in C by typecasting

Time:10-15

I have a struct that is defined as

typedef struct
{
    int id;
    char* name;
    float percentage;
}student_t;

And in a given function

void student_tDeleter(void* val_ref) {
    
}

I understand that if a function had to take in void* ptr as its parameter, I have to do type cast in order to access to its memeber variables, but the following code won't work for some reason

void student_tDeleter(void* val_ref) {
    free((student_t*)val_ref->id);
    free((student_t*)val_ref->name);
    free((student_t*)val_ref->percentage);
    free(val_ref)
    val_ref = NULL;
}

Compiler says that ```warning: dereferencing void* pointer error: request for memeber "id/name/percentage" in something not a struct or union

I thought its the parentheses. So I added two extra parentheses

void student_tDeleter(void* val_ref) {
    free(((student_t*)val_ref)->id);
    free(((student_t*)val_ref)->name);
    free(((student_t*)val_ref)->percentage);
    val_ref = NULL;
}

But compiler says that

  free(((student_t*)val_ref)->id);
error: incompatible type for argument 1 of ‘freefree(((student_t*)val_ref)->percentage);
 note: expected ‘void *’ but argument is of type ‘floatextern void free (void *__ptr) __THROW;

How do I properly free() struct memebers? Any reply is appreciated.

CodePudding user response:

Operator precedence

-> beats cast.

(student_t*)val_ref->id
// is like
(student_t*)(val_ref->id)

Instead use

((student_t*)val_ref)->id

Free pointers

@Vlad from Moscow nicely points out code should not attempt to "free" a float nor int.


Repaired code

As free(NULL) is OK, let us also allow student_tDeleter(NULL).

void student_tDeleter(void* val_ref) {
  if (val_ref) {
    free(((student_t*)val_ref)->name);
    free(val_ref)
  }
}

CodePudding user response:

The data members id and percentage are not pointers.

typedef struct
{
    int id;
    char* name;
    float percentage
}student_t;

So it does not make a sense to apply the function free to objects of the type int and float.

If the data member name points to a dynamically allocated memory then you need to write

free( ( ( student_t * )val_ref )->name );

and then

free(val_ref)

Pay attention to that casting is an unary operator while the operator -> is a postfix operator that has higher precedence than unary operators.

CodePudding user response:

Non-dynamically allocated members of your struct will be handled by freeing the struct. You only need to separately free any dynamically allocated struct members.

For example:

typedef struct a {
    int b;
    char *c;
} a_t;

a_t * create_a() {
    a_t *new_a = malloc(sizeof(a_t));

    new_a->b = 42;
    new_a->c = malloc(new_a->b);

    return new_a;
}

void delete_a(void *d) {
    a_t *a = (a_t *)d;

    free(a->c);
    free(a);
}
  • Related