是否有其他方法可以释放 C 中动态分配的内存 - 不使用 free() 函数?

发布于 2024-07-17 00:02:29 字数 245 浏览 8 评论 0原文

我正在学习测试,我想知道其中是否有任何一个相当于 free(ptr):

 malloc(NULL); 

 calloc(ptr); 

 realloc(NULL, ptr); 

 calloc(ptr, 0); 

 realloc(ptr, 0);

据我所知,这些都不起作用,因为 free() 函数实际上告诉 C ptr 之后的内存再次可用供其使用。 抱歉,这是一个菜鸟问题,但我们将不胜感激。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

┈┾☆殇 2024-07-24 00:02:29

实际上,最后一个相当于调用free()。 仔细阅读 realloc() 的规范,您会发现它可以重新分配数据,或者更改分配的大小(尤其是当新大小大于旧大小时,可能会移动周围的数据),它也可以释放内存。 事实上,您不需要其他功能; 它们都可以用realloc()来编写。 并不是任何心智正常的人都会这样做……但这是可以做到的。

请参阅 Steve Maguire 的“编写可靠的代码”,完整剖析malloc() 函数系列。 请参阅 ACCU 网站,完整剖析阅读“编写可靠代码”的危险。 我不相信它像评论中所说的那么糟糕 - 尽管它完全缺乏对 const 的处理确实已经过时了(可以追溯到 90 年代初,当时 C89 还很新,并且未广泛全面实施)。


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

C99 标准说:

7.20.3.3 The malloc 函数

剧情简介

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

描述

malloc函数为大小由size和指定的对象分配空间
其值是不确定的。

退货

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

7.20.3.4 realloc 函数

剧情简介

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

描述

realloc函数释放ptr指向的旧对象并返回一个
指向具有 size 指定大小的新对象的指针。 新内容
对象应与释放之前的旧对象相同,最多为新旧大小中的较小者。 新对象中超出旧对象大小的任何字节都具有不确定的值。

如果 ptr 是空指针,则 realloc 函数的行为类似于 malloc 函数
指定尺寸。 否则,如果 ptr 与之前返回的指针不匹配
calloc、malloc 或 realloc 函数,或者空间已通过调用释放
对于 free 或 realloc 函数,行为是未定义的。 如果记忆是新的
对象无法分配,旧对象没有被释放,它的值没有改变。

退货

realloc 函数返回一个指向新对象的指针(它可能具有相同的值)
值作为指向旧对象的指针),或者如果新对象无法被调用则为空指针
已分配。


除了因额外标头和函数而进行的编辑性更改外,ISO/IEC 9899:2011 标准与 C99 的表述相同,但在第 7.22.3 节中而不是在第 7.20.3 节中。


realloc 的 Solaris 10 (SPARC) 手册页显示:

realloc() 函数将 ptr 的块指针的大小更改为 size 字节,并返回指向(可能移动的)块的指针。 内容将保持不变,直至新旧尺寸中较小的一个。 如果块的新大小需要块的移动,则释放块的先前实例化的空间。 如果新大小较大,则未指定块的新分配部分的内容。 如果 ptr 为 NULL,对于指定的大小,realloc() 的行为类似于 malloc()。 如果size为0且ptr不是空指针,则释放指向的空间。

这是一个非常明确的“它像 free() 一样工作”的声明。

然而,MacOS X 10.5 或 BSD 的说法有所不同,这再次证实了我第一段中“没有人头脑正常”的部分。


当然,还有 C99 基本原理...它说:

7.20.3 内存管理功能

这些定义中对空指针和零长度分配请求的处理
功能部分是由支持这种范式的愿望引导的:

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 */
 }

据报道,这种编码风格并不一定得到委员会的认可,但已广泛流行
使用。

某些实现已针对零字节的分配请求返回非空值。
尽管这种策略在理论上具有区分“无”和“零”(未分配的指针与指向零长度空间的指针)的优势,但它具有更引人注目的优势
需要零长度对象概念的理论上的缺点。 由于此类物体
无法声明,它们存在的唯一方式就是通过这样的方式
分配请求。

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

C89 的悄然变化

依赖于大小为零的分配请求的程序返回非空指针
会有不同的行为。

[...]

7.20.3.4 realloc 函数

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

C99 的一个新特性:更改了 realloc 函数,以明确指向的
对象被释放,分配一个新对象,新对象的内容与
旧物体的尺寸,最多为两个尺寸中较小的一个。 C89 尝试指定新对象与旧对象是同一对象,但可能具有不同的地址。 这冲突了
标准的其他部分假设对象的地址在其运行期间是恒定的
寿命。 此外,当大小为零时支持实际分配的实现不支持
对于这种情况,必须返回一个空指针。 C89 似乎需要 null 返回值,并且
委员会认为这限制太多。


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

C89 明确表示:“如果 size 为零且 ptr 不是空指针,则它指向的对象将被释放。” 那么他们似乎在 C99 中删除了这句话?

是的,他们删除了该句子,因为它包含在开头句子中:

realloc函数释放ptr指向的旧对象

那里没有回旋余地; 旧对象被释放。 如果请求的大小为零,那么您将返回 malloc(0) 可能返回的任何内容,这通常是一个空指针,但也可能是一个非空指针,也可以返回到 < code>free() 但不能合法地取消引用。

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.

总以为 2024-07-24 00:02:29
realloc(ptr, 0);

相当于 free(ptr); (尽管我不建议这样使用它!)

另外:这两个调用彼此等效(但不等于 free):

realloc(NULL,size)
malloc(size)
realloc(ptr, 0);

is equivalent to free(ptr); (although I wouldn't recommended its use as such!)

Also: these two calls are equivalent to each other (but not to free):

realloc(NULL,size)
malloc(size)
把人绕傻吧 2024-07-24 00:02:29

最后一个 - realloc(ptr, 0) - 很接近。 它将释放任何分配的块并用最小的分配替换它(我的 Mac OS X 10.5 联机帮助页)。 检查本地联机帮助页以了解它在您的系统上的作用。

也就是说,如果ptr指向一个实体对象,您将取回其大部分内存。


Debian Lenny 的手册页同意 米奇Jonathan...BSD 在这方面真的与 Linux 不同吗?


从有问题的手册页:

realloc() 函数尝试更改指向的分配大小
to 通过 ptr 来调整大小,并返回 ptr。 [...]
如果 size 为零并且 ptr 不为 NULL,则创建一个新的,
分配最小大小的对象并释放原始对象。


Linux 和Solaris 手册页非常干净,并且'89 标准:realloc(ptr,0) 的工作方式类似于free(ptr)。 上面的 Mac OS 手册页和 Jonathan 引用的标准不太清楚,但似乎留下了打破等价性的空间。

我一直想知道为什么会有这种差异:“表现得像自由”对我来说似乎很自然。 我有权访问的两种实现都包含一些环境变量驱动的可调性,但 BSD 版本接受更多选项一些示例:

 MallocGuardEdges 如果设置,则在前后添加一个防护页 
                                每个大块。   
  
 MallocDoNotProtectPrelude    If set, do not add a guard page before large
                              blocks, even if the MallocGuardEdges envi-
                              ronment variable is set.

 MallocDoNotProtectPostlude   If set, do not add a guard page after large
                              blocks, even if the MallocGuardEdges envi-
                              ronment variable is set.

 MallocPreScribble 如果设置,则填充已分配的内存 
                                带有 0xaa 字节。   这增加了可能性 
                                引擎盖,一个程序做出假设 
                                新分配的内存的内容 
                                将失败。 
  
 MallocScribble               If set, fill memory that has been deallo-
                              cated with 0x55 bytes.  This increases the
                              likelihood that a program will fail due to
                              accessing memory that is no longer allo-
                              cated.

在正常模式下,“最小尺寸的对象”可能什么都不是(即相当于free),而是带有一些防护装置的某物。 接受它的价值。

The last one--realloc(ptr, 0)--comes close. It will free any allocated block and replace it with a minimal allocation (says my Mac OS X 10.5 manpage). Check your local manpage to see what it does on your system.

That is, if ptr pointed at a substantial object, you'll get back most of its memory.


The man page on Debian Lenny agrees with Mitch and Jonathan...does BSD really diverge from Linux on this?


From the offending man page:

The realloc() function tries to change the size of the allocation pointed
to by ptr to size, and returns ptr. [...]
If size is zero and ptr is not NULL, a new,
minimum sized object is allocated and the original object is freed.


The linux and solaris man pages are very clean, and the '89 standard: realloc(ptr,0) works like free(ptr). The Mac OS manpage above, and the standard as quoted by Jonathan are less clear but seems to leave room to break the equivalence.

I've been wondering why the difference: the "act like free" interpretation seems very natural to me. Both of the implementations I have access to include some environment variable driven tunablity, but the BSD version accepts many more options Some examples:

 MallocGuardEdges             If set, add a guard page before and after
                              each large block.  
 MallocDoNotProtectPrelude    If set, do not add a guard page before large
                              blocks, even if the MallocGuardEdges envi-
                              ronment variable is set.

 MallocDoNotProtectPostlude   If set, do not add a guard page after large
                              blocks, even if the MallocGuardEdges envi-
                              ronment variable is set.

and

 MallocPreScribble            If set, fill memory that has been allocated
                              with 0xaa bytes.  This increases the likeli-
                              hood that a program making assumptions about
                              the contents of freshly allocated memory
                              will fail.
 MallocScribble               If set, fill memory that has been deallo-
                              cated with 0x55 bytes.  This increases the
                              likelihood that a program will fail due to
                              accessing memory that is no longer allo-
                              cated.

Possibly the "minimum sized object" is nothing (i.e. equivalent to free) in the normal modes, but something with some of the guards in place. Take that for what it's worth.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文