[英]about malloc() and free() in C
我有以下C代码:
#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
int a;
}node;
int main()
{
node * n;
printf("\n%d\n",n->a);
n = (node *) malloc ( sizeof( node ));
printf("\n%d\n",n->a);
n->a = 6;
printf("\n%d\n",n->a);
free(n);
printf("\n%d\n",n->a);
n->a = 4;
printf("\n%d\n",n->a);
return 0;
}
获得的输出为:
1314172
0
6
0
4
我的问题是什至在free(n)之后,为什么n-> a = 0,我们又如何将它重新分配为n-> a = 4的任何值?
不释放使n指向的内存块无效吗?
free(n);
n->a = 4; // is not guaranteed to work, might crash on some implementations
调用未定义的行为。
为什么n-> a = 0,我们又如何将其重新分配为n-> a = 4之类的任何值?
那是因为未定义行为意味着任何事情都会发生。 您不能依靠它。
PS:请勿编写此类代码。
编辑 :
乔纳森(Jonathan)注意到,您的代码在free()
之前取消调用n
,然后取消引用n
。
node * n; //n is not initialized
printf("\n%d\n",n->a); //dereferencing a wild pointer invokes UB.
重复使用释放的指针类似于为您租用的汽车制作钥匙的副本,将汽车交还,然后在您将汽车交还给租车地点后尝试使用该钥匙进入汽车。 您也许可以摆脱它,但是您不应该这样做,而且它经常会给您带来麻烦。
不,免费可能对关联的内存没有任何作用。 引用它是无效的。 其他进程/您的进程可能已覆盖内存,或者,如果您不走运,数据可能就如您所愿。
由您决定是否不引用释放的内存。
当取消引用未分配内存的指针时,该行为是不确定的。 这意味着它可以做任何事情。 它可能会触发错误,或者可能会执行其他操作。
在大多数情况下,如果您free
一些内存,则不会立即重新使用该内存,并且操作系统不会立即将其回收。 这意味着您的应用程序仍然可以访问该内存,并且仍将包含其先前的值。 您通常可以在没有错误的情况下对其进行读取或写入,但是您一定不能依赖此行为 。
如果您在许多不同的环境中运行此代码,您会发现在某些环境中它始终可以工作,在某些环境中它总是会触发错误,但是在许多其他环境中,它“大部分时间”都可以工作。 这使得C很难调试! :)
内存块被释放。 那并不意味着你不能写它。 这意味着您不得写信。 机器不会阻止您执行此操作(通常,有些工具(例如电围栏)会阻止它运行)
如您将来所见; 您最终会意外地这样做; 通常会发生坏事(tm)
在大多数针对带有MMU的硬件(例如x86)的操作系统上,实际读取内存错误的唯一方法是未映射应用程序地址。 由于MMU没有告诉它与物理地址相关联的数据的条目,该数据与应用程序所请求的逻辑地址相关联,因此MMU引起中断,操作系统接管该操作。
但是大多数操作系统除了为应用程序提供所需大小的连续内存块外,并没有为代表应用程序管理内存。 操作系统也不允许应用程序在MMU中混乱,因为大多数MMU不够智能,无法让应用程序安全地执行操作而不会对其他程序造成负面影响(意外或恶意)。
因此,当您使用malloc()
某些操作时,如果您的应用尚未在其现有地址空间中放置该位置,它将向操作系统询问更多信息,但是当您稍后使用free()
时,除非该操作恰好位于在应用程序地址空间的最末端,您无法将其退还给操作系统,以使该内存区域在尝试读取时会导致错误。
有一些方法可以做到这一点,例如,使用mmap()
,但这并不是使用该函数的正确原因。
大多数操作系统将分配一定的最小空间,该最小空间将等于或大于您请求的空间。 拨打免费电话后,该空间将不会返回操作系统,而是随身携带以备将来使用。 因此,您可以摆脱上面编写的内容。
但是严格来说,这被归类为“未定义”行为。 但是您大多数时候都可以摆脱它。 只是不要养成习惯;)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.