C语言 malloc(0) 返回什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2132273/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:15:15  来源:igfitidea点击:

What does malloc(0) return?

clinuxpointersmallocrealloc

提问by manav m-n

What does malloc(0)return?

什么malloc(0)回报?

Would the answer be same for realloc(malloc(0),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;
}

Output from Linux GCC:

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?

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

EDIT:

编辑:

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

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

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;
}

采纳答案by Alok Singhal

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):

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

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

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

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

该标准是这样说的realloc(ptr, size)

  • if ptris NULL, it behaves like malloc(size),
  • otherwise (ptris not NULL), it deallocates the old object pointer to by ptrand returns a pointer to a new allocated buffer. But if sizeis 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.
  • 如果ptrNULL,它的行为就像malloc(size)
  • 否则 ( ptris not NULL),它释放指向 by 的旧对象指针ptr并返回一个指向新分配缓冲区的指针。但是如果size是 0,C89 说效果等价于free(ptr)。有趣的是,我在 C99 草案(n1256 或 n1336)中找不到该声明。在 C89 中,在这种情况下返回的唯一合理值是NULL.

So, there are two cases:

所以,有两种情况:

  • malloc(0)returns NULLon an implementation. Then your realloc()call is equivalent to realloc(NULL, 0). That is equivalent to malloc(0)from above (and that is NULLin 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 notequivalent.
  • malloc(0)NULL实现的回报。那么你的realloc()调用就相当于realloc(NULL, 0). 这相当于malloc(0)从上面(NULL在这种情况下)。
  • malloc(0)返回非NULL. 然后,调用等效于free(malloc(0))。在这种情况下,malloc(0)realloc(malloc(0), 0)等价的。

Note that there is an interesting case here: in the second case, when malloc(0)returns non-NULLon success, it may still return NULLto 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.

请注意,这里有一个有趣的情况:在第二种情况下,当malloc(0)返回非NULL成功时,它可能仍然返回NULL以指示失败。这将导致类似的调用:realloc(NULL, 0),相当于malloc(0),可能返回也可能不返回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-NULLptris not equivalent to free(ptr). I just tried this with gcc -std=c99, and the above is equivalent to free(ptr).

我不确定 C99 中的遗漏是否是一种疏忽,或者是否意味着在 C99 中,realloc(ptr, 0)对于 non-NULLptr不等同于free(ptr). 我刚刚试过这个gcc -std=c99,上面的相当于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().

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

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

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

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:

现在你问的问题是:malloc(0) == realloc(malloc(0), 1024). 在这种情况下,让我们假设malloc(0)LHS 和 RHS 上的 都返回 non- NULL。那么,它们肯定是不同的。此外,来自malloc()LHS的返回值尚未被free()d,因此任何其他malloc(), calloc(), 或realloc()可能不会返回该值。这意味着,如果您将条件写为:

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

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

你不会看到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;
}

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

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

回答by Prasoon Saurav

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

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

From C99[Section 7.20.3]

来自C99[第 7.20.3 节]

The order and contiguity of storage allocated by successive calls to the calloc, malloc, and realloc functions is unspeci?ed. 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- de?ned: 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.

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

回答by Prasoon Saurav

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

在 C89 中, malloc(0) 依赖于实现——我不知道 C99 是否已经修复了这个问题。在 C++ 中,使用:

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.

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

回答by Kornel Kisielewicz

C99 standard

C99标准

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.

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

回答by unwind

The comp.lang.c FAQhas the followingto say:

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

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.

ANSI/ISO 标准说它可以做任何一个;行为是实现定义的(见问题 11.33)。可移植代码必须注意不要调用 malloc(0),或者为可能出现 null 返回做好准备。

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

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

回答by Patrick Schlüter

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

有一点还没有人愿意谈论,在你的第一个程序中,realloc长度为 0 与free.

from the Solaris man page:

从 Solaris 手册页:

The realloc()function changes the size of the block pointed to by ptrto sizebytes 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 ptris NULL, realloc()behaves like malloc()for the specified size. If sizeis 0and ptris 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.

realloc()函数将指向的块的大小更改ptrsize字节并返回指向(可能移动的)块的指针。内容将保持不变,直至新旧尺寸中的较小者。如果ptrNULL,则realloc()行为类似于malloc()指定大小。如果size0ptr不是空指针,则指向的空间可供应用程序进一步分配,但不会返回给系统。仅在应用程序终止时才将内存返回给系统。

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

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

回答by Christoph

See C99, section 7.20.3:

参见 C99,第 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()).

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

回答by Patrick

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

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

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.

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

回答by user9876

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

void *ptr = malloc(0);

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

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

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 ptris a valid pointer to a memory block of size zero. The mallocimplementation saves this information in an implementation-specific way. reallocknows the (implementation-specific) way to figure out that ptrpoints to a memory block of size zero.

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

(How malloc/realloc/freedo 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 reallocand free).

(如何malloc/ realloc/free做,这是实现特定的。一种可能是分配4个字节以上要求并存储大小之前的内存块。在这种情况下,((int *)ptr)[-1]将给内存块的大小,这是0你永远不应该这样做从您的代码中,它仅供reallocfree)使用。