我正在学习和测试C中的内存分配,我想测试如果调用free()
会发生什么。
我预计在运行下面的程序后可能会出现分段错误或指针NULL
。但是,我仍然可以像输出一样成功打印字符串。我还试图释放str
两次,然后在输出2发生时出错。
以前分配的内存似乎已成功解除分配,但内存中的数据未清除。那是对的吗?如果是这种情况,程序什么时候会清理那些解除分配的内存空间?如果数据被解除分配但没有清理,那是否安全?
上述任何问题的答案都会有所帮助!谢谢!
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Hello, World!\n");
char *str = (char *)malloc(24);
char *str2 = "tutorialspoint";
strcpy(str, str2);
free(str);
printf("[str] %s\n", str);
return 0;
}
Hello, World!
[str] tutorialspoint
main(83218,0x7fff9d2aa3c0) malloc: *** error for object 0x7fb0b2d00000: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
谢谢大家的回复。现在我明白在C中有一些未定义的行为(UB),这有助于我理解其他让我困惑的事情,例如写入超出分配范围的字符串(比如下面的代码片段中的内容)。这导致UB根据wiki,但程序不会崩溃。
如果我弄错了,请随意纠正我!
char *str = (char *)malloc(0);
char *str2 = "tutorialspoint";
strcat(str, str2);
printf("[str] %s, [addr] %p\n", str, str);
答案 0 :(得分:6)
您需要学习未定义行为的概念。
即使您在释放字符串后打印字符串并且“正常工作”,但这并不意味着它有效。这只是当行为被称为未定义时可能发生的事情之一,在这种情况下它就是。
此外,指针不会是NULL
,除非你这样做
free(ptr);
ptr = NULL;
和free()
不会将所有字节都设置为0
。
free()
函数就像它的名字所暗示的那样。它允许malloc()
再次使用free()
d块。指针指向的数据可能仍然保持不变,这就是为什么你仍然可以在free()
之后打印之前的内容的原因。但是,如果您在free()
之后取消引用指针,或者数据是否仍然存在,或者是否被完全或部分覆盖,则绝对无法保证会发生什么。
如果在free()
之后取消引用指针,有一件事你知道,行为是未定义的。
答案 1 :(得分:4)
当你致电free
时,它允许指向内存用于其他目的。尝试读取或写入已释放的内存会调用undefined behavior。
仅仅因为记忆已被放弃并不一定意味着它已被物理擦除。
类比:假设您在酒店房间的桌子上留了一本书。您离开酒店,但仍然有钥匙卡。如果你回到房间,那本书可能会在那里,或者可能没有。