为什么在C中释放struct还有数据?

当我运行此代码时:

#include  typedef struct _Food { char name [128]; } Food; int main (int argc, char **argv) { Food *food; food = (Food*) malloc (sizeof (Food)); snprintf (food->name, 128, "%s", "Corn"); free (food); printf ("%d\n", sizeof *food); printf ("%s\n", food->name); } 

我还是得到了

 128 Corn 

虽然我已经解放了食物。 为什么是这样? 记忆真的被释放了吗?

当你释放“食物”时,你说你完成了它。 但是,指针食物仍然指向相同的地址,并且该数据仍然存在(将不必要时释放的每一位内存归零都是太多开销)

基本上是因为这是一个很小的例子,这是有效的。 如果在free和print语句之间有任何其他malloc调用,那么你有可能不会看到这个,并且很可能会以某种糟糕的方式崩溃。 你不应该依赖这种行为。

释放内存不一定会覆盖它的内容。

没有什么比像免费食物了:)当你“释放”某些东西时,它意味着同样的空间再次被其他东西所使用。 这并不意味着用垃圾填满。 其次,指针值没有改变 – 如果你正在认真编码,你应该在释放它之后将指针设置为NULL,这样就不会发生像这样的潜在垃圾访问。

sizeof是一个编译时操作,因此内存分配不会改变它的工作方式。

free不会擦除内存,只是将块标记为未使用。 即使你分配了几百兆的内存,你的指针仍然可能不会被覆盖(现代计算机有很多 RAM)。 但是,在释放内存后,您将无法再依赖其值。

查看您的开发环境是否具有内存分配调试设置 – 有些设置可以在free时使用0xDEADBEEF覆盖块。

此外,您可能希望在调用free之后立即采用将指针设置为NULL的习惯(以帮助鼓励程序尽早崩溃)。

free告诉内存分配器它可以重用那个内存块,没有别的。 它不会用零或任何东西覆盖块 – 幸运的是,因为这可能是一个非常昂贵的操作! 它所做的是使指针的任何进一步解引用未定义,但“未定义”行为很可能意味着“做与以前相同的事情” – 你不能依赖它。 在另一个编译器,另一个runime,或在其他条件下,它可能会抛出exception,或终止程序,或破坏其他数据,所以…只是不要。

在C中没有“struct have data”或“struct没有数据”这样的东西。在你的程序中,你有一个指向内存中某处的指针。 只要此内存属于您的应用程序(即未返回到系统),它将始终包含某些内容。 那些“东西”可能是完全垃圾,或者看起来或多或少有意义。 此外,内存可能包含看似有意义的垃圾(以前存储在那里的数据的剩余部分)。

这正是您在实验中观察到的。 一旦你解除了分析结构,以前被它占用的内存正式包含垃圾。 但是,该垃圾可能仍然类似于在解除分配时存储在该结构对象中的原始数据的位。 在你的情况下,你很幸运,所以数据看起来完好无损。 不要指望它 – 下次它可能会完全被摧毁。

就C语言而言,您正在做的事情构成了未定义的行为。 您不能检查解除分配的结构是否“有数据”。 你问的“为什么”问题并不存在于C语言领域。

在某些系统中,释放内存将从地址空间取消映射,如果在取消分配后尝试访问它,您将获得核心转储或等效内容。

在win32系统中(至少通过XP),情况并非如此。 微软在32位Windows上制作他们的内存子系统故意使内存块保持兼容,以保持与释放后使用内存的众所周知的MS-DOS应用程序的兼容性。

在MS-DOS编程模型中,没有映射或进程空间的概念,因此这些类型的错误在Windows95下作为DOS模式程序执行之前不会显示为程序失败。

十多年来,这种行为持续存在于32位Windows中。 现在可能会改变现在在Vista和7等系统中撤销旧版兼容性。