提问人:smellyourbooks 提问时间:8/4/2023 更新时间:8/5/2023 访问量:91
free() on char* 被 valgrind 识别为无效
free() on char* recognized as invalid by valgrind
问:
我正在尝试释放存在于 char** 数组中的 char* 指针,但 valgrind 将此操作确定为无效。
这是我正在做的事情的一个简单例子:
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*));
}
这是我感到困惑的地方 - 我可以通过以下循环访问元素:
for(size_t i=0;i<10;i++)
printf("%s", B->floors[i]); //assume that a valid string exists at each floors[i]!
我正在尝试释放分配的内存,如下所示:
for(size_t i=0;i<10;i++)
free(B->floors[i]);
free(B);
请原谅缺少针对 NULL 的 malloc() 检查,为了简洁起见,我将其删掉了。
Valgrind 确定操作是 。然而,如果我可以通过访问单个 char* 元素,我是否应该能够使用相同的语法通过简单地将函数调用从 to 切换出来释放它(我从这个 stackoverflow 答案中得到了这个想法)?free(B->floors[i])
Invalid free() / delete / delete[] / realloc()
B-floors[i]
printf()
free()
第二个调用工作正常。free()
我的程序按预期执行,但我想摆脱内存泄漏 - 因此使用了 valgrind。如果有帮助,我在执行 valgrind 时使用 gcc 的开关和参数。-Werror -ggdb
--track-origins=yes --leak-check=full
答:
5赞
David Ranieri
8/5/2023
#1
这里:
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(...); // or malloc + memcpy if strdup is not available
}
最后:
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);
评论
0赞
Andrew Henle
8/5/2023
这只会得到一个包含 20 个指针的未初始化数组。我怀疑这还不是全部需要的,但这个问题是不完整的......char *
0赞
smellyourbooks
8/5/2023
虽然这处理了堆分配,但如果我现在不初始化嵌入的 char* 指针,valgrind 会抱怨这个和这个.这就是我最初使用 malloc 循环并将嵌入的 char* 指针设置为默认值的原因。Conditional jump or move depends on uninitialised value(s)
Uninitialised value was created by a heap allocation
0赞
David Ranieri
8/5/2023
@AndrewHenle每个指针都需要指向堆栈上的某个有效地址或保留 or + 当然,我假设 OP 知道这一点,但无论如何都进行了编辑。strdup
malloc
memcpy
0赞
0___________
8/5/2023
@DavidRanieri为什么在堆栈上?
1赞
smellyourbooks
8/5/2023
我只想得出结论,这个答案是完美的。事实证明,当我应该在导致内存问题的内部函数中使用时,我正在通过运算符分配 char* 指针值。谢谢@DavidRanieri的所有帮助!=
memcpy
评论
B->floors
是一个指针,但你永远不会让它指向任何地方。您需要例如 在循环之前。当然,一旦你完成了它(在循环释放每个元素之后)。B->floors = malloc(10 * sizeof *B->floors)
free(B->floors)
floors
char *floors[];
B
struct building *B = malloc(sizeof(*B) + 10 * sizeof(B->floors[0]));