malloc(0) 返回什么?

发布于 2024-08-18 16:29:52 字数 1338 浏览 3 评论 0原文

malloc(0) 返回什么?

realloc(malloc(0),0) 的答案是否相同?

#include<stdio.h>
#include<malloc.h>
int main()
{
        printf("%p\n", malloc(0));
        printf("%p\n", realloc(malloc(0), 0));
        return 0;
}

Linux GCC 的输出:

manav@manav-workstation:~$ gcc -Wall mal.c
manav@manav-workstation:~$ ./a.out
0x9363008
(nil)
manav@manav-workstation:~$

malloc(0) 的输出每次都会发生变化。这是标准答案吗?除了学术研究之外,为什么会有人对获得这样的指针感兴趣呢?

编辑:

如果malloc(0)返回虚拟指针,那么以下代码如何工作:

int main()
{
    void *ptr = malloc(0);
    printf("%p\n", realloc(ptr, 1024));
    return 0;
}

编辑:

以下代码为每次迭代输出“可能” 。为什么它不应该失败?

#include<stdio.h>
#include<malloc.h>
int main()
{

        int i;
        void *ptr;
        printf("Testing using BRUTE FORCE\n");
        for (i=0; i<65000; i++)
        {
                ptr = malloc(0);
                if (ptr == realloc(ptr, 1024))
                        printf("Iteration %d: possible\n", i);
                else
                {
                        printf("Failed for iteration %d\n", i);
                        break;
                }
        }
        return 0;
}

What does malloc(0) return?

Would the answer be same for realloc(malloc(0),0)?

#include<stdio.h>
#include<malloc.h>
int main()
{
        printf("%p\n", malloc(0));
        printf("%p\n", realloc(malloc(0), 0));
        return 0;
}

Output from Linux GCC:

manav@manav-workstation:~$ gcc -Wall mal.c
manav@manav-workstation:~$ ./a.out
0x9363008
(nil)
manav@manav-workstation:~$

The output keep changing everytime for malloc(0). Is this a standard answer? And why would anyone be interested in getting such a pointer, other than academic research?

EDIT:

If malloc(0) returns dummy pointer, then how does following works:

int main()
{
    void *ptr = malloc(0);
    printf("%p\n", realloc(ptr, 1024));
    return 0;
}

EDIT:

The following code outputs "possible" for every iteration. Why should it not fail ?

#include<stdio.h>
#include<malloc.h>
int main()
{

        int i;
        void *ptr;
        printf("Testing using BRUTE FORCE\n");
        for (i=0; i<65000; i++)
        {
                ptr = malloc(0);
                if (ptr == realloc(ptr, 1024))
                        printf("Iteration %d: possible\n", i);
                else
                {
                        printf("Failed for iteration %d\n", i);
                        break;
                }
        }
        return 0;
}

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

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

发布评论

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

评论(9

秋意浓 2024-08-25 16:29:52

其他人已经回答了 malloc(0) 的工作原理。我将回答您提出的尚未得到解答的问题之一(我认为)。问题是关于 realloc(malloc(0), 0) 的:

malloc(0) 返回什么? realloc(malloc(0),0) 的答案是否相同?

标准对于realloc(ptr, size)是这么说的:

  • 如果ptrNULL,它的行为就像malloc(size) code>,
  • 否则(ptr 不是 NULL),它会释放 ptr 指向的旧对象指针,并返回指向新分配的缓冲区的指针。但如果size为0,C89表示效果相当于free(ptr)。有趣的是,我在 C99 草案(n1256 或 n1336)中找不到该声明。在 C89 中,在这种情况下返回的唯一合理值是 NULL。

因此,有两种情况:

  • malloc(0) 在实现上返回 NULL。那么您的 realloc() 调用相当于 realloc(NULL, 0)。这相当于上面的 malloc(0) (在本例中为 NULL)。
  • malloc(0) 返回非NULL。然后,该调用相当于free(malloc(0))。在这种情况下,malloc(0)realloc(malloc(0), 0) 不等价。

请注意,这里有一个有趣的情况:在第二种情况下,当 malloc(0) 成功返回非 NULL 时,它仍然可能返回 NULL code> 表示失败。这将导致类似的调用:realloc(NULL, 0),这相当于malloc(0),它可能返回也可能不返回NULL< /代码>。

我不确定 C99 中的遗漏是否是一个疏忽,或者是否意味着在 C99 中,realloc(ptr, 0) 对于非 NULL ptr 不等于 free(ptr)。我刚刚用gcc -std=c99尝试过,上面相当于free(ptr)

编辑:我想我明白您的困惑是什么:

让我们看一下示例代码中的片段:

ptr = malloc(0);
if (ptr == realloc(ptr, 1024))

上面与 malloc(0) == realloc(malloc(0) 不同,1024)。在第二个中,malloc() 调用进行了两次,而在第一个中,您将先前分配的指针传递给realloc()

我们先分析第一段代码。假设 malloc(0) 在成功时不返回 NULL,则 ptr 具有有效值。当您执行 realloc(ptr, 1024) 时,realloc() 基本上会为您提供一个大小为 1024 的新缓冲区,并且 ptr 变为无效的。符合要求的实现可能会返回与 ptr 中已有的地址相同的地址。因此,您的 if 条件可能会返回 true。 (但是请注意,在 realloc(ptr, 1024) 之后查看 ptr 的值可能是未定义的行为。)

现在您问的问题是:malloc(0 ) == realloc(malloc(0), 1024)。在本例中,我们假设左侧和右侧的 malloc(0) 均返回非 NULL。那么,它们就保证是不同的。此外,LHS 上 malloc() 的返回值尚未被 free() 释放,因此任何其他 malloc()calloc()realloc() 可能不会返回该值。这意味着,如果您将条件写为:

if (malloc(0) == realloc(malloc(0), 1024)
    puts("possible");

您将不会在输出中看到 possible(除非 malloc()realloc()失败并返回NULL)。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    void *p1;
    void *p2;

    p1 = malloc(0);
    p2 = realloc(p1, 1024);
    if (p1 == p2)
        puts("possible, OK");

    /* Ignore the memory leaks */
    if (malloc(0) == realloc(malloc(0), 1024))
        puts("shouldn't happen, something is wrong");
    return 0;
}

在 OS X 上,我的代码运行时没有输出任何内容。在 Linux 上,它打印 possible, OK

Others have answered how malloc(0) works. I will answer one of the questions that you asked that hasn't been answered yet (I think). The question is about realloc(malloc(0), 0):

What does malloc(0) return? Would the answer be same for realloc(malloc(0),0)?

The standard says this about realloc(ptr, size):

  • if ptr is NULL, it behaves like malloc(size),
  • otherwise (ptr is not NULL), it deallocates the old object pointer to by ptr and returns a pointer to a new allocated buffer. But if size is 0, C89 says that the effect is equivalent to free(ptr). Interestingly, I can't find that statement in C99 draft (n1256 or n1336). In C89, the only sensible value to return in that case would be NULL.

So, there are two cases:

  • malloc(0) returns NULL on an implementation. Then your realloc() call is equivalent to realloc(NULL, 0). That is equivalent to malloc(0) from above (and that is NULL in this case).
  • malloc(0) returns non-NULL. Then, the call is equivalent to free(malloc(0)). In this case, malloc(0) and realloc(malloc(0), 0) are not equivalent.

Note that there is an interesting case here: in the second case, when malloc(0) returns non-NULL on success, it may still return NULL to indicate failure. This will result in a call like: realloc(NULL, 0), which would be equivalent to malloc(0), which may or may not return NULL.

I am not sure if the omission in C99 is an oversight or if it means that in C99, realloc(ptr, 0) for non-NULL ptr is not equivalent to free(ptr). I just tried this with gcc -std=c99, and the above is equivalent to free(ptr).

Edit: I think I understand what your confusion is:

Let's look at a snippet from your example code:

ptr = malloc(0);
if (ptr == realloc(ptr, 1024))

The above is not the same as malloc(0) == realloc(malloc(0), 1024). In the second, the malloc() call is made twice, whereas in the first, you're passing a previously allocated pointer to realloc().

Let's analyze the first code first. Assuming malloc(0) doesn't return NULL on success, ptr has a valid value. When you do realloc(ptr, 1024), realloc() basically gives you a new buffer that has the size 1024, and the ptr becomes invalid. A conforming implementation may return the same address as the one already in ptr. So, your if condition may return true. (Note, however, looking at the value of ptr after realloc(ptr, 1024) may be undefined behavior.)

Now the question you ask: malloc(0) == realloc(malloc(0), 1024). In this case, let's assume that both the malloc(0) on the LHS and RHS returns non-NULL. Then, they are guaranteed to be different. Also, the return value from malloc() on the LHS hasn't been free()d yet, so any other malloc(), calloc(), or realloc() may not return that value. This means that if you wrote your condition as:

if (malloc(0) == realloc(malloc(0), 1024)
    puts("possible");

you won't see possible on the output (unless both malloc() and realloc() fail and return NULL).

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    void *p1;
    void *p2;

    p1 = malloc(0);
    p2 = realloc(p1, 1024);
    if (p1 == p2)
        puts("possible, OK");

    /* Ignore the memory leaks */
    if (malloc(0) == realloc(malloc(0), 1024))
        puts("shouldn't happen, something is wrong");
    return 0;
}

On OS X, my code didn't output anything when I ran it. On Linux, it prints possible, OK.

別甾虛僞 2024-08-25 16:29:52

就 C99 而言,malloc(0)实现定义的

来自 C99 [第 7.20.3 节]

通过连续调用calloc分配的存储的顺序和连续性,
malloc 和 realloc 函数未指定。如果分配则返回指针
成功时进行适当对齐,以便可以将其分配给指向任何类型对象的指针
然后用于访问分配的空间中的此类对象或此类对象的数组
(直到空间被明确释放)。已分配对象的生命周期延长
从分配到释放。每个这样的分配应产生一个指向
与任何其他对象不相交的对象。返回的指针指向开始(最低字节
地址)分配的空间。如果无法分配空间,则为空指针
回来了。 如果请求的空间大小为零,则行为是执行 -
已定义:要么返回空指针,要么行为就好像大小是某个
非零值,但返回的指针不得用于访问对象。


malloc(0) is Implementation Defined as far as C99 is concerned.

From C99 [Section 7.20.3]

The order and contiguity of storage allocated by successive calls to the calloc,
malloc, and realloc functions is unspecified
. The pointer returned if the allocation
succeeds is suitably aligned so that it may be assigned to a pointer to any type of object
and then used to access such an object or an array of such objects in the space allocated
(until the space is explicitly deallocated). The lifetime of an allocated object extends
from the allocation until the deallocation. Each such allocation shall yield a pointer to an
object disjoint from any other object. The pointer returned points to the start (lowest byte
address) of the allocated space. If the space cannot be allocated, a null pointer is
returned. If the size of the space requested is zero, the behavior is implementation-
defined
: either a null pointer is returned, or the behavior is as if the size were some
nonzero value, except that the returned pointer shall not be used to access an object.

陌伤浅笑 2024-08-25 16:29:52

在 C89 中,malloc(0) 取决于实现 - 我不知道 C99 是否已修复此问题。在 C++ 中,使用:

char * p = new char[0];

定义良好 - 您将获得一个有效的非空指针。当然,您不能使用指针来访问它所指向的内容而不调用未定义的行为。

至于为什么存在这种情况,它对于某些算法来说很方便,并且意味着您不需要在代码中进行零值测试。

In C89, malloc(0) is implementation dependent - I don't know if C99 has fixed this or not. In C++, using:

char * p = new char[0];

is well defined - you get a valid, non-null pointer. Of course, you can't use the pointer to access what it points to without invoking undefined behaviour.

As to why this exists, it is convenient for some algorithms, and means you don't need to litter your code with tests for zero values.

上课铃就是安魂曲 2024-08-25 16:29:52

C99标准

如果无法分配空间,则
返回空指针。如果尺寸
所请求的空间为零,则
行为是实现定义的:
返回空指针,或者
行为就像大小一样
一些非零值,除了
返回的指针不得用于
访问对象。

C99 standard

If the space cannot be allocated, a
nullpointer is returned. If the size
of the space requested is zero, the
behavior is implementation-defined:
either a null pointer is returned, or
the behavior is as if the size were
some nonzero value, except that the
returned pointer shall not be used to
access an object.

野却迷人 2024-08-25 16:29:52

comp.lang.c 常见问题解答以下说:

ANSI/ISO 标准表示它可能
做其中一个;的行为是
实现定义的(参见问题
11.33)。可移植代码必须注意不要调用 malloc(0),或者
为空的可能性做好准备
返回。

因此,最好避免使用 malloc(0)

The comp.lang.c FAQ has the following to say:

The ANSI/ISO Standard says that it may
do either; the behavior is
implementation-defined (see question
11.33). Portable code must either take care not to call malloc(0), or be
prepared for the possibility of a null
return.

So, it's probably best to avoid using malloc(0).

长安忆 2024-08-25 16:29:52

有一点还没有人愿意谈论,在你的第一个程序中,长度为 0 的 reallocfree 是一样的。

来自 Solaris 手册页:

realloc()函数改变指向的块的大小
ptr 转换为 size 字节并返回指向(可能已移动)块的指针。截止日期前内容将保持不变
新旧尺寸中较小的一个。如果ptrNULL,则realloc()
对于指定的大小,其行为类似于 malloc()。如果大小0
并且ptr不是空指针,指向的空间已被创建
但可供应用程序进一步分配
没有返回到系统。内存返回给系统
仅在应用程序终止时。

如果一个人不知道这可能会带来糟糕的惊喜(发生在我身上)。

One point nobody cared to talk about yet, in your first program is that realloc with length 0 is the same thing as free.

from the Solaris man page:

The realloc() function changes the size of the block pointed
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 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 made
available for further allocation by the application, though
not returned to the system. Memory is returned to the system
only upon termination of the application.

If one doesn't know that it can be a source of bad surprise (happened to me).

岁月静好 2024-08-25 16:29:52

参见 C99,第 7.20.3 节:

如果请求的空间大小是
零,行为是
实现定义:要么为 null
返回指针,或者行为
就好像大小是非零的
值,除了返回的
指针不得用于访问
对象。

这对于所有三个分配函数(即calloc()malloc()realloc())都有效。

See C99, section 7.20.3:

If the size of the space requested is
zero, the behavior is
implementationdefined: either a null
pointer is returned, or the behavior
is as if the size were some nonzero
value, except that the returned
pointer shall not be used to access an
object.

This is valid for all three allocation functions (ie calloc(), malloc() and realloc()).

罪歌 2024-08-25 16:29:52

我认为这取决于。
我检查了 Visual Studio 2005 源代码并在 _heap_alloc 函数中看到了这一点:

if (size == 0)
    size = 1;

我认为在许多情况下您可能需要一个有效的指针,即使在要求零字节时也是如此。
这是因为这种一致的行为使检查指针变得更加容易,因为: 如果您有一个非 NULL 指针,那么就可以了;如果你有一个 NULL 指针,你可能会遇到问题。
这就是为什么我认为大多数实现都会返回一个有效的指针,即使在要求零字节时也是如此。

I think it depends.
I checked the Visual Studio 2005 sources and saw this in the _heap_alloc function:

if (size == 0)
    size = 1;

I think that in many cases you may want a valid pointer, even when asking for zero bytes.
This is because this consistent behavior makes it easier to check your pointers because: if you have a non-NULL pointer it's OK; if you have a NULL pointer you probably have a problem.
That's why I think that most implementations will return a valid pointer, even when asking for zero bytes.

清音悠歌 2024-08-25 16:29:52

如果 malloc(0) 返回虚拟指针,那么以下内容如何工作:

void *ptr = malloc(0);

printf("%p\n", realloc(ptr, 1024));

我不知道你所说的“虚拟指针”是什么意思。如果 malloc(0) 返回非 NULL,则 ptr 是指向大小为零的内存块的有效指针。 malloc 实现以特定于实现的方式保存此信息。 realloc 知道(特定于实现的)方法来确定 ptr 指向大小为零的内存块。

malloc/realloc/free 如何做到这一点是特定于实现的。一种可能是分配比请求多 4 个字节并存储大小在这种情况下,((int *)ptr)[-1] 将给出内存块大小,即 0。从您的代码来看,它仅供 reallocfree 使用)。

If malloc(0) returns dummy pointer, then how does following works:

void *ptr = malloc(0);

printf("%p\n", realloc(ptr, 1024));

I don't know what you mean by "dummy pointer". If malloc(0) returns non-NULL, then ptr is a valid pointer to a memory block of size zero. The malloc implementation saves this information in an implementation-specific way. realloc knows the (implementation-specific) way to figure out that ptr points to a memory block of size zero.

(How malloc/realloc/free do this is implementation-specific. One possibility is to allocate 4 bytes more than requested and store the size just before the memory block. In that case, ((int *)ptr)[-1] would give the memory block size, which is 0. You should never do this from your code, it's only for use by realloc and free).

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