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 ‘free’
free(((student_t*)val_ref)->percentage);
note: expected ‘void *’ but argument is of type ‘float’
extern void free (void *__ptr) __THROW;
How do I properly free() struct memebers? Any reply is appreciated.
CodePudding user response:
->
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 free
ing 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);
}