2011-06-28 141 views
0
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 
} 

现在我的问题是,作为free()功能工作作为指针p指向它的NULLNULL值的语句relloc。这20个字节会被释放吗?malloc和realloc函数

+3

使用'“%p”'来打印指针。 –

+4

C中的注释用* forward *斜杠表示,而不是* backward *斜杠,我在编辑中保留了未修正的内容。 –

+4

如果p为NULL,则无法对其解除引用... –

回答

5

不,它可能不会在全部的情况下被释放。 C99在7.20.3.4 The realloc function中有这样的说法:

如果无法分配新对象的内存,则不会释放旧对象并且其值保持不变。

现在你可能认为零字节的分配不可能失败,但标准没有强制要求。它说,对于零大小的对象:

如果所请求的空间大小为零,则行为是实现定义的:或者返回空指针,或者行为就好像大小是一些非空字符一样,零值,但不应使用返回的指针访问对象。

所以,如果你的实现是其中的一个是返回NULL的零大小分配,它需要每个分配一些内务信息,和存储领域是如此完全不能存储另一个管家标题,并且它不够聪明只是将当前分配分割并将大部分分配返回到舞台,它可能会失败一个零大小的realloc,因此不会释放原始内存。

现在,这是一个(非常)优势案例,取决于实施过程中做出的大量决策,其中大部分对于具有编写经验的人来说可能看起来很奇怪。不幸的是,我们要允许边缘情况以及:-)

如果真的担心你,我只是改变:

p=(int *)realloc(p,0); 

到:

free (p) ; p = NULL; 

其他几点。

  1. 评论marjers是正斜杠/,而不是反斜杠。
  2. 无论您的实现是否针对零分配分配返回NULL,都不允许在最后一行中取消引用p。看到我上面的第二个引用,它指出:“除了返回的指针不能用于访问对象”。
  3. 你不应该真的从malloc -type调用返回值。这是昏暗的黑暗过去之后的宿醉,之后C有void*,malloc返回char*。现在这样做的问题是,如果您忘记包含stdlib.h,问题可能会隐藏起来。
+0

我' d还想补充说'p = realloc(p,n);'是不正确的。使用'realloc'的正确方法是void * tmp = realloc(p,n); if(!tmp){/ * handle realloc error * /} p = tmp;' –

+0

很好的解释。我甚至意识到他使用了反斜杠。 –

0

首先这是非常依赖于平台的。您的通话realloc绝对不工作的自由...使用指针像你一样将得到某种形式的分割故障或崩溃,如果它没有设置P到NULL指针...

无论realloc将“免费“20个字节还是不是(再次)完全取决于执行该操作的OS /库realloc

编辑:

从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,但其他实现可以改变这种行为......

+0

谁降低了这一点?在C99中,具有0大小的'realloc'是实现定义的。它可以与'free'或'malloc(0)'相同。它应该是不明确的,所以我认为这是标准方面的一个改进。 –

+0

@Chris,我相信C99已经被您引用满意答案之一。 – littleadv

+0

@littleadv - 它有。我从iPhone发布信息,所以我稍微落后于其他人。 (否则_I_会引用标准) –

1

如果给定大小到realloc是0和一个分配的指针,然后它will free the memory the pointer points to and will return NULL

这带来了一个问题:

你为什么这样做,那么:

printf("%u",*p); \\ printing the value as 0 

p为NULL,在这一点上,和你还在解引用它。做什么的?你期望在这里发生什么?

+0

NULL其实我读NULL意味着0所以它必须指向第零的位置我想知道它的数据 – jack

+0

@jack - NULL不一定是0(虽然它通常是)。无论如何,取消引用NULL会带来未定义的行为(崩溃,内存损坏,蓝屏等),并且您明确地在代码中执行此操作。你**不能**看到“零位”中的内容,因为它不是你允许访问的内存。 – littleadv

+0

对不起@littleadv我只是继续做不同的语法来知道他们如何工作,所以我想看到零位置。我对unaryoperatos有疑问,但它说,你必须等待20分钟,我可以问这里 – jack

0

的C90标准具体表示:

如果尺寸是零并且PTR是不是一个空指针,它指向该对象被释放。

所以这就是C90和C++实现应该如何表现 - 很好,简单和直接。

但是,由于某些原因,该句子已从C99标准中删除。

POSIX目前拥有C90标准中的句子。但是,奥斯汀集团(负责处理POSIX标准化的一些方面)has a defect open on this。注意缺陷报告表明,BSD有realloc(ptr,0)以下行为:

的realloc(PTR,0)仅给出了ALLOC失败NULL,PTR不变,错误号是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删除了这句话。但是请注意,无论C99可能需要说些什么,许多(大多数?)实现都会在调用realloc(ptr,0)时释放该块。