malloc和realloc函数
int main( ) { int *p; p=(int *)malloc(20); printf("%u",p); \\ printing some memory adress p=(int *)realloc(p,0); printf("%u",p); \\ printing as 0 printf("%u",*p); \\ printing the value as 0 }
现在我的问题是语句relloc
作为free()
函数工作,因为指针p
指向其中的NULL
和NULL
值。 这20个字节会被释放吗?
不,在任何情况下都可能无法释放。 C99在7.20.3.4 The realloc function
有这个说法7.20.3.4 The realloc function
:
如果无法分配新对象的内存,则不会释放旧对象,并且其值不会更改。
现在您可能认为零字节的分配不可能失败,但标准并未强制要求。 它说,对于零大小的对象:
如果请求的空间大小为零,则行为是实现定义的:返回空指针,或者行为就像大小是非零值一样,除了返回的指针不应用于访问宾语。
因此,如果您的实现是零大小分配不返回NULL的实现之一,并且它需要每个分配的一些内务处理信息,并且内存区域已满,您甚至无法存储另一个内务处理标头,并且仅仅分割当前分配并将其大部分返回到竞技场并不够智能,它可能会失败零大小的重新分配,因此不会释放原始内存。
现在这是一个(非常)边缘的情况,取决于在实现中做出的许多决定,其中大多数对于具有编写经验的人来说可能看起来很奇怪。 不幸的是,我们也必须考虑边缘情况:-)
如果它真的让你担心,我只会改变:
p=(int *)realloc(p,0);
成:
free (p) ; p = NULL;
其他几点。
- 评论marjers是正斜线
/
而不是反斜杠。 - 在最后一行中不允许取消引用
p
,无论您的实现是否为零大小分配返回NULL。 请参阅上面的第二个引用,其中指出:“除了返回的指针不得用于访问对象”之外。 - 您不应该从
malloc
类型调用中转换返回值。 在C有一个void*
之前,这是昏暗的黑暗过去的宿醉,而malloc
返回了char*
。 现在这样做的问题是,如果您忘记包含stdlib.h
,可能会向您隐藏问题。
如果赋予realloc
的大小为0以及分配的指针,则它将释放指针指向的内存并返回NULL 。
这带来了下一个问题:
你为什么这样做:
printf("%u",*p); \\ printing the value as 0
p
为NULL,您仍然在解除引用它。 做什么的? 你期望在这里发生什么?
首先,这是非常依赖平台的。 你的realloc
调用绝对不能像一个免费的…使用指针就像你所做的那样会得到某种分段错误或崩溃如果它确实将p设置为NULL
指针…
realloc
是否将“释放”20个字节(再次)完全取决于实现该realloc
的OS /库。
编辑:
从GNU C lib:
/* REALLOC_ZERO_BYTES_FREES should be set if a call to realloc with zero bytes should be the same as a call to free. This is required by the C standard. Otherwise, since this malloc returns a unique pointer for malloc(0), so does realloc(p, 0). */
默认情况下,这被定义为1,但其他实现可以改变该行为……
C90标准具体说:
如果size为零且ptr不是空指针,则释放它指向的对象。
所以这就是C90和C ++实现应该如何表现 – 好,简单,直接。
但是,出于某种原因,该句子已从C99标准中删除。
POSIX目前的句子符合C90标准。 但是,奥斯汀集团(处理POSIX标准化的某些方面) 在这方面存在缺陷 。 请注意,缺陷报告指示BSD对realloc(ptr,0)
具有以下行为:
realloc(ptr,0)仅在alloc失败时给出NULL,ptr不变,errno为ENOMEM
我读到的是说ptr
没有被释放(我没有BSD系统来检查这个)。
换句话说, realloc(ptr,0)
应该/将会发生什么样的混乱 – 我不会依赖它来释放内存。 打电话给你free()
你想做什么。
我想知道C99删除那句话的理由是什么……
事实上,C99标准实际上似乎排除了realloc(ptr,0)
简单地释放块(即,它似乎根本没有定义此实现)。 C99标准说:
…如果无法分配新对象的内存,则不会释放旧对象,并且其值不会更改
返回
realloc函数返回指向新对象的指针(可能与指向旧对象的指针具有相同的值),如果无法分配新对象,则返回空指针。
因此,如果realloc()
返回NULL
则无法分配新对象,并且不能释放旧对象。 但是如果realloc()
返回非NULL,那么你仍然必须释放对象(或者必须释放一些新的内存对象)。 换句话说,如果realloc(ptr,0)
返回NULL
那么你仍然负责释放ptr
。 如果realloc(ptr,0)
返回一个非空指针,那么你负责释放返回的任何指针。
我想也许这就是为什么C99删除了这句话。 但是请注意,当调用realloc(ptr,0)
时,许多(大多数?)实现会释放块,无论C99可能对此有什么看法。