malloc(0)返回什么?

man*_*m-n 53 c linux malloc pointers realloc

什么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;
}
Run Code Online (Sandbox Code Playgroud)

linux gcc的输出:

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

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

编辑:

如果malloc(0)返回虚拟指针,那么后续工作原理如何:

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

编辑:

以下代码为每次迭代输出"可能".为什么不失败?

#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;
}
Run Code Online (Sandbox Code Playgroud)

Alo*_*hal 44

其他人已经回答了如何malloc(0)运作 我会回答你提出的一个尚未回答的问题(我认为).问题是realloc(malloc(0), 0):

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

该标准说明了这一点realloc(ptr, size):

  • 如果ptrNULL,它表现得像malloc(size),
  • 否则(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以指示失败.这将导致一个类似于的调用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))
Run Code Online (Sandbox Code Playgroud)

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

让我们先分析第一个代码.假设成功后malloc(0)没有返回NULL,ptr则具有有效值.当你这样做时realloc(ptr, 1024),realloc()基本上会给你一个大小为1024的新缓冲区,并且ptr变得无效.符合要求的实现可以返回与已经存在的地址相同的地址ptr.所以,你的if病情可能会恢复正常.(注意,但是,查看ptrafter 的值realloc(ptr, 1024)可能是未定义的行为.)

现在你问的问题:malloc(0) == realloc(malloc(0), 1024).在这种情况下,让我们假设malloc(0)LHS和RHS都返回非NULL.然后,他们保证是不同的.此外,从返回值malloc()的LHS尚未free()ð还,所以任何其他的malloc(),calloc()realloc()可能不会返回值.这意味着如果您将条件写为:

if (malloc(0) == realloc(malloc(0), 1024)
    puts("possible");
Run Code Online (Sandbox Code Playgroud)

你不会看到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;
}
Run Code Online (Sandbox Code Playgroud)

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


Pra*_*rav 34

malloc(0)是关于C99的实现定义.

来自C99 [第7.20.3节]

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

  • PJ Plauger(C标准委员会成员)在他的一篇文章中说他们对此有很大的争论,最后他们加油并将其留给实施. (9认同)
  • @Manav:它可能被用作标记指针:它是一个明确区别于任何其他有效指针的指针,并且它不是NULL. (4认同)
  • @BlueRaja:这是他们的工作,争论各种提案的利弊.在这种情况下,总是返回空指针对某些人来说很方便,而对其他人来说,进行0大小的分配很方便.委员会*应该*考虑两者.不幸的是,他们提出的妥协只能帮助特定于平台的代码,对任何试图移植代码的人来说都是无用的. (3认同)
  • 在malloc(0)的情况下返回非空指针是一致的,并且有助于将其与返回NULL的错误情况区分开来,NULL可以从malloc的任何参数返回,例如malloc(4). (2认同)
  • @TMN:因为"每个这样的分配都会产生一个指向与任何其他对象不相交的对象的指针." (2认同)
  • @TMN:啊,我认为Joachim说,malloc(0)返回的任何两个指针`a`和`b`都会满足`a!= b`.(当然,假设malloc不为malloc(0)返回NULL.) (2认同)

小智 15

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

char * p = new char[0];
Run Code Online (Sandbox Code Playgroud)

定义得很好 - 你得到一个有效的非空指针.当然,您无法使用指针访问它指向的内容而不调用未定义的行为.

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

  • @R.我认为关键是C99不要求*实现为`malloc(0)`返回'0`或非'`0`. (6认同)

Kor*_*icz 5

C99标准

如果无法分配空间,则返回nullpointer.如果请求的空间大小为零,则行为是实现定义的:返回空指针,或者行为就像大小是非零值一样,但返回的指针不应用于访问对象.


unw*_*ind 5

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

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

所以,最好避免使用malloc(0).

  • @Manav:它实际上也适用于NULL,`realloc(NULL,1024)`与`malloc(1024)`相同` (3认同)