I am attempting to free char* pointers that exist within a char** array, but valgrind is determining this operation as invalid.
Here is a simple example of what I'm doing:
struct building{
int propertyPrice;
int totalArea;
char** floors;
}
int main(){
struct building* B = malloc(sizeof(struct building));
for(size_t i=0;i<10;i++)
B->floors[i] = malloc(20 * sizeof(char*));
}
Here's where I'm confused - I can access the elements with the following loop:
for(size_t i=0;i<10;i++)
printf("%s", B->floors[i]); //assume that a valid string exists at each floors[i]!
I am attempting to free the allocated memory as follows:
for(size_t i=0;i<10;i++)
free(B->floors[i]);
free(B);
Please excuse the lack of malloc() check against NULL, I'm cutting that out for brevity.
Valgrind determines that the operation free(B->floors[i])
is Invalid free() / delete / delete[] / realloc()
. Yet, if I can access the individual char* elements through B-floors[i]
, shouldn't I be able to free it using the same syntax by just switching the function call from printf()
to free()
(I got the idea from this stackoverflow answer)?
The second free()
call works perfectly fine.
My program is executing as expected, but I'd like to get rid of memory leaks - hence the usage of valgrind. If it's helpful, I'm using the -Werror -ggdb
switches for gcc and the --track-origins=yes --leak-check=full
arguments when executing valgrind.
Here:
for(size_t i=0;i<10;i++)
B->floors[i] = malloc(20 * sizeof(char*));
B->floors
is used uninitialized.
You need to reserve space for 10 elements:
B->floors = malloc(10 * sizeof(char*));
then you can fill the jagged array:
for (int i = 0; i < 10; i++) {
B->floors[i] = strdup(...); // or malloc + memcpy if strdup is not available
}
finally:
for (int i = 0; i < 10; i++) {
free(B->floors[i]);
}
free(B->floors);
Since floors
is the last member of the array you can use it as a "flexible array member":
struct building* B = malloc(sizeof(struct building) + (sizeof(char *) * 10));
in this case you don't call free(B->floors);
at the end.