我释放后仍然可以打印一个字符串吗?

时间:2017-07-19 18:48:25

标签: c memory-management malloc free

我正在学习和测试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

输出2

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);

2 个答案:

答案 0 :(得分:6)

您需要学习未定义行为的概念

即使您在释放字符串后打印字符串并且“正常工作”,但这并不意味着它有效。这只是当行为被称为未定义时可能发生的事情之一,在这种情况下它就是。

此外,指针不会是NULL,除非你这样做

free(ptr);
ptr = NULL;

free()不会将所有字节都设置为0

free()函数就像它的名字所暗示的那样。它允许malloc()再次使用free() d块。指针指向的数据可能仍然保持不变,这就是为什么你仍然可以在free()之后打印之前的内容的原因。但是,如果您在free()之后取消引用指针,或者数据是否仍然存在,或者是否被完全或部分覆盖,则绝对无法保证会发生什么。

如果在free()之后取消引用指针,有一件事你知道,行为是未定义的。

答案 1 :(得分:4)

当你致电free时,它允许指向内存用于其他目的。尝试读取或写入已释放的内存会调用undefined behavior

仅仅因为记忆已被放弃并不一定意味着它已被物理擦除。

类比:假设您在酒店房间的桌子上留了一本书。您离开酒店,但仍然有钥匙卡。如果你回到房间,那本书可能会在那里,或者可能没有。