英文:
free() on char* recognized as invalid by valgrind
问题
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.
英文:
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.
答案1
得分: 5
以下是翻译好的部分:
这里:
for(size_t i=0;i<10;i++)
B->floors[i] = malloc(20 * sizeof(char*));
`B->floors` 未经初始化。
您需要为10个元素预留空间:
B->floors = malloc(10 * sizeof(char*));
然后您可以填充这个多维数组:
for (int i = 0; i < 10; i++) {
B->floors[i] = strdup(...); // 或者如果没有 strdup 可用,可以使用 malloc + memcpy
}
最后:
for (int i = 0; i < 10; i++) {
free(B->floors[i]);
}
free(B->floors);
由于`floors`是数组的最后一个成员,您可以将其用作"柔性数组成员":
struct building* B = malloc(sizeof(struct building) + (sizeof(char *) * 10));
在这种情况下,您不需要在最后调用 `free(B->floors);`。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论