有没有一种替代方法来释放C中动态分配的内存 - 不使用free()函数? [英] Is there an alternative way to free dynamically allocated memory in C - not using the free() function?

查看:155
本文介绍了有没有一种替代方法来释放C中动态分配的内存 - 不使用free()函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在考试,我想知道这些是否等同于免费(ptr):

 的malloc(NULL); 

calloc(ptr);

realloc(NULL,ptr);

calloc(ptr,0);

realloc(ptr,0);

根据我的理解,这些都不会工作,因为free()函数实际上告诉C ptr后的内存可供使用。对不起,这是一个noob的问题,但帮助将不胜感激。

解决方案

其实最后一个相当于调用 free()。仔细阅读 realloc()的规范,您将发现它可以重新分配数据,或更改分配的大小(特别是如果新的大小更大比旧的,可能会移动数据),它也可以释放内存。其实你不需要其他功能;它们都可以用 realloc()编写。不是任何人在正确的心态会这样做...但可以做到。



请参阅Steve Maguire的编写固体代码,以完整剖析 malloc()家族的危险的功能。请参阅 ACCU 网站,全面剖析阅读写入固体代码的危险。我不相信它与评论一样糟糕,尽管它完全缺乏对 const 的处理,但是它可以回溯到90年代初,当C89仍然是新的并且没有被广泛实施时)。






D McKee关于MacOS X 10.5(BSD)的注释是有趣...



C99标准说:



7.20.3.3 malloc函数




简介




  #include< stdlib.h> 
void * malloc(size_t size);




描述



malloc函数为大小指定大小的对象分配空间,
的值为不确定。



返回



malloc函数返回空指针或指向分配空间的指针。




7.20.3.4 realloc函数




简介




  #include< stdlib.h> 
void * realloc(void * ptr,size_t size);




描述



realloc函数取消分配由ptr指向的旧对象,并返回一个
指针,该对象的大小由size指定。新的
对象的内容应与释放之前的旧对象的内容相同,直到新旧尺寸中的较小者为止。超过旧对象大小的新对象中的任何字节都有不确定的值。



如果ptr是空指针,则realloc函数的行为与
指定大小。否则,如果ptr与先前由
calloc,malloc或realloc函数返回的指针不匹配,或者如果该空间已由释放或realloc函数调用
释放,则该行为是未定义的。如果新的
对象的内存不能被分配,则旧的对象不会被释放,其值不变。



返回



realloc函数返回指向新对象的指针(可能具有与旧对象的指针相同的
值),如果新对象不能为$ b,则返回空指针$ b分配。







除了编辑更改,因为额外的标题和功能, ISO / IEC 9899:2011标准与C99相同,但在7.22.3节而不是7.20.3中。






realloc的Solaris 10(SPARC)手册页说:


realloc()函数将块指针的大小更改为ptr到字节大小并返回一个指向(可能移动的)块的指针。内容将不变,新旧尺寸较小。如果块的新大小需要块的移动,则块的先前实例化的空间将被释放。如果新的大小较大,则新分配的块的内容未指定。如果ptr为NULL,则realloc()的行为与指定大小的malloc()一样。如果大小为0,并且ptr不是空指针,则指向的空格将被释放。


这是一个非常明确的它的工作原理free()'语句。



然而,MacOS X 10.5或BSD说的不一样,重申了我第一段中的没有人在正确的想法。






当然有 C99理由 ...说:



7.20。 3内存管理功能




在这些
函数的定义中处理空指针和零长度分配请求部分由支持这一范式的愿望指导:




  OBJ * p; //指向OBJ的变量列表
/ *初始分配* /
p =(OBJ *)calloc(0,sizeof(OBJ));
/ * ... * /
/ *重新分配,直到大小结算* /
while(1){
p =(OBJ *)realloc((void *)p,c * sizeof(OBJ));
/ *更改c的值或断开循环* /
}




这种编码风格,不一定被委员会认可,据报道是广泛的
使用。



有些实现已经返回零字节的分配请求的非空值。
虽然这种策略具有区分无和零(未分配指针与指向零长度空间的指针)的理论优势,但它具有更加引人注目的
理论上的缺点,要求零长度对象的概念。由于这样的对象
不能被声明,所以它们可能存在的唯一方式是通过这样的
分配请求。



C89委员会决定不接受零长度对象的想法。因此,分配
函数可能会为零字节的分配请求返回空指针。请注意,这种处理并不排除上述范例。



C89中的QUIET更改



依赖的程序在大小为零的分配请求返回非空指针
将表现不同。


[...] p>

7.20.3.4 realloc函数




空的第一个参数是允许的。如果第一个参数不为空,第二个参数为0,则调用将释放第一个参数指向的内存,并返回空值为
; C99与不允许零大小的对象的策略一致。



C99的一个新功能:更改了realloc函数,使其成为清除指向
对象被释放,分配一个新对象,并且新对象的内容与旧对象的
相同,直到两个大小中的较小者为止。 C89尝试指定新对象与旧对象是同一个对象,但可能具有不同的地址。这将
与标准的其他部分冲突,假定对象的地址在其
生命周期内是不变的。此外,当大小为零时支持实际分配的实现不是
必然返回一个空指针。 C89似乎需要一个零返回值,而
委员会认为这太限制了。







托马斯·帕德龙 - 麦卡锡 观察


C89明确说:如果大小为零,ptr不是一个空指针,则它指向的对象被释放。所以他们似乎在C99中删除了这句话?


是的,他们已经删除了那句话,因为它被开头的句子包含:


realloc函数取消分配由ptr指向的旧对象


那里没有扭动的房间旧对象被释放。如果所请求的大小为零,那么您可以回复任何 malloc(0)可能返回,通常(通常)是一个空指针,但可能是非空指针也可以返回到 free(),但无法合法解除引用。


I am studying for a test, and I was wondering if any of these are equivalent to free(ptr):

 malloc(NULL); 

 calloc(ptr); 

 realloc(NULL, ptr); 

 calloc(ptr, 0); 

 realloc(ptr, 0);

From what I understand, none of these will work because the free() function actually tells C that the memory after ptr is available again for it to use. Sorry that this is kind of a noob question, but help would be appreciated.

解决方案

Actually, the last of those is equivalent to a call to free(). Read the specification of realloc() very carefully, and you will find it can allocate data anew, or change the size of an allocation (which, especially if the new size is larger than the old, might move the data around), and it can release memory too. In fact, you don't need the other functions; they can all be written in terms of realloc(). Not that anyone in their right mind would do so...but it could be done.

See Steve Maguire's "Writing Solid Code" for a complete dissection of the perils of the malloc() family of functions. See the ACCU web site for a complete dissection of the perils of reading "Writing Solid Code". I'm not convinced it is as bad as the reviews make it out to be - though its complete lack of a treatment of const does date it (back to the early 90s, when C89 was still new and not widely implemented in full).


D McKee's notes about MacOS X 10.5 (BSD) are interesting...

The C99 standard says:

7.20.3.3 The malloc function

Synopsis

#include <stdlib.h>
void *malloc(size_t size);

Description

The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.

Returns

The malloc function returns either a null pointer or a pointer to the allocated space.

7.20.3.4 The realloc function

Synopsis

#include <stdlib.h>
void *realloc(void *ptr, size_t size);

Description

The realloc function deallocates the old object pointed to by ptr and returns a pointer to a new object that has the size specified by size. The contents of the new object shall be the same as that of the old object prior to deallocation, up to the lesser of the new and old sizes. Any bytes in the new object beyond the size of the old object have indeterminate values.

If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size. Otherwise, if ptr does not match a pointer earlier returned by the calloc, malloc, or realloc function, or if the space has been deallocated by a call to the free or realloc function, the behavior is undefined. If memory for the new object cannot be allocated, the old object is not deallocated and its value is unchanged.

Returns

The realloc function returns a pointer to the new object (which may have the same value as a pointer to the old object), or a null pointer if the new object could not be allocated.


Apart from editorial changes because of extra headers and functions, the ISO/IEC 9899:2011 standard says the same as C99, but in section 7.22.3 instead of 7.20.3.


The Solaris 10 (SPARC) man page for realloc says:

The realloc() function changes the size of the block pointer to by ptr to size bytes and returns a pointer to the (possibly moved) block. The contents will be unchanged up to the lesser of the new and old sizes. If the new size of the block requires movement of the block, the space for the previous instantiation of the block is freed. If the new size is larger, the contents of the newly allocated portion of the block are unspecified. If ptr is NULL, realloc() behaves like malloc() for the specified size. If size is 0 and ptr is not a null pointer, the space pointed to is freed.

That's a pretty explicit 'it works like free()' statement.

However, that MacOS X 10.5 or BSD says anything different reaffirms the "No-one in their right mind" part of my first paragraph.


There is, of course, the C99 Rationale...It says:

7.20.3 Memory management functions

The treatment of null pointers and zero-length allocation requests in the definition of these functions was in part guided by a desire to support this paradigm:

OBJ * p; // pointer to a variable list of OBJs
    /* initial allocation */
p = (OBJ *) calloc(0, sizeof(OBJ));
     /* ... */
     /* reallocations until size settles */
 while(1) {
    p = (OBJ *) realloc((void *)p, c * sizeof(OBJ));
         /* change value of c or break out of loop */
 }

This coding style, not necessarily endorsed by the Committee, is reported to be in widespread use.

Some implementations have returned non-null values for allocation requests of zero bytes. Although this strategy has the theoretical advantage of distinguishing between "nothing" and "zero" (an unallocated pointer vs. a pointer to zero-length space), it has the more compelling theoretical disadvantage of requiring the concept of a zero-length object. Since such objects cannot be declared, the only way they could come into existence would be through such allocation requests.

The C89 Committee decided not to accept the idea of zero-length objects. The allocation functions may therefore return a null pointer for an allocation request of zero bytes. Note that this treatment does not preclude the paradigm outlined above.

QUIET CHANGE IN C89

A program which relies on size-zero allocation requests returning a non-null pointer will behave differently.

[...]

7.20.3.4 The realloc function

A null first argument is permissible. If the first argument is not null, and the second argument is 0, then the call frees the memory pointed to by the first argument, and a null argument may be returned; C99 is consistent with the policy of not allowing zero-sized objects.

A new feature of C99: the realloc function was changed to make it clear that the pointed-to object is deallocated, a new object is allocated, and the content of the new object is the same as that of the old object up to the lesser of the two sizes. C89 attempted to specify that the new object was the same object as the old object but might have a different address. This conflicts with other parts of the Standard that assume that the address of an object is constant during its lifetime. Also, implementations that support an actual allocation when the size is zero do not necessarily return a null pointer for this case. C89 appeared to require a null return value, and the Committee felt that this was too restrictive.


Thomas Padron-McCarthy observed:

C89 explicitly says: "If size is zero and ptr is not a null pointer, the object it points to is freed." So they seem to have removed that sentence in C99?

Yes, they have removed that sentence because it is subsumed by the opening sentence:

The realloc function deallocates the old object pointed to by ptr

There's no wriggle room there; the old object is deallocated. If the requested size is zero, then you get back whatever malloc(0) might return, which is often (usually) a null pointer but might be a non-null pointer that can also be returned to free() but which cannot legitimately be dereferenced.

这篇关于有没有一种替代方法来释放C中动态分配的内存 - 不使用free()函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆