malloc(0)中有什么意义?

时间:2010-01-07 17:43:14

标签: c malloc

刚看到这个code:

artist = (char *) malloc(0);

我想知道为什么会这样做?

17 个答案:

答案 0 :(得分:115)

根据规范,malloc(0)将返回“空指针或可以成功传递给free()的唯一指针”。

这基本上可以让你什么都不分配,但仍然可以将“artist”变量传递给free(),而不用担心。出于实际目的,它几乎与做:

artist = NULL;

答案 1 :(得分:46)

C标准(C17 7.22.3 / 1)说:

  

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

因此,malloc(0)可以返回NULL或可能无法解除引用的有效指针 。在任何一种情况下,在其上调用free()都是完全有效的。

我并不认为malloc(0)有多大用处,例如在循环中调用malloc(n)的情况除外,n可能为零。

查看链接中的代码,我认为作者有两个误解:

  • malloc(0)返回有效指针始终
  • free(0)不好。

因此,他确保artist和其他变量始终具有一些“有效”值。评论说:// these must always point at malloc'd data

答案 2 :(得分:10)

malloc(0)行为是特定于实现的。该库可以返回NULL或具有常规malloc行为,没有分配内存。无论它做什么,都必须在某处记录。

通常,它返回一个有效且唯一的指针,但不应该取消引用。另请注意,即使它实际上没有分配任何内容,它也会消耗内存。

可以重新分配非null malloc(0)指针。

尽管使用malloc(0)逐字逐句。它主要用于动态分配为零字节且您不关心验证它时。

答案 3 :(得分:5)

本页的其他地方有一个答案,“malloc(0)将返回一个有效的内存地址,其范围将取决于正在分配内存的指针类型”。这个陈述不正确(我没有足够的声誉来直接评论这个答案,所以不能直接把这个评论放在那里)。

执行malloc(0)将自动分配正确大小的内存。 malloc函数不知道你将其结果投射到了什么。 malloc函数完全依赖于您提供的大小编号作为参数。你需要做malloc(sizeof(int))来获得足够的存储来保存int,例如,不是0。

答案 4 :(得分:3)

除非代码依赖于特定于实现的行为,否则

malloc(0)对我没有任何意义。如果代码是可移植的,那么它必须考虑到malloc(0)的NULL返回不是失败的事实。那么为什么不将NULL分配给artist,因为这是一个有效的成功结果,并且代码更少,并且不会让维护程序员花时间搞清楚它?

malloc(SOME_CONSTANT_THAT_MIGHT_BE_ZERO)malloc(some_variable_which_might_be_zero)可能也有它们的用途,尽管如果值为0,你还是要特别注意不要将NULL返回视为失败,但是0的大小应该是没关系。

答案 5 :(得分:3)

这里有很多半真正的答案,所以这里有很多事实。 malloc()的手册页说:

  

如果size为0,则malloc()返回NULL或稍后可以的唯一指针值          成功传递给free()。​​

这意味着,绝对不能保证malloc(0)的结果是唯一的或不是NULL。唯一的保证是由free()的定义提供的,同样,这是man-page所说的内容:

  

如果ptr为NULL,则不执行任何操作。

因此,无论malloc(0)返回什么,都可以安全地传递给free()。但NULL指针也是如此。

因此,撰写 artist = malloc(0); 绝不比写作 artist = NULL;

更好

答案 6 :(得分:2)

不可否认,我以前从未见过这个,这是我第一次看到这种语法,可以说是一个功能矫枉过正的经典案例。结合里德的回答,我想指出有一个类似的东西,看起来像一个重载函数realloc

  • foo为非NULL且大小为零,realloc(foo, size);。当你传入一个非NULL指针并且大小为零来重新分配时,realloc的行为就好像你已经调用了free(...)
  • foo为NULL且大小不为零且大于1,realloc(foo, size);。传入NULL指针并且大小不为零时,realloc的行为就像调用malloc(...)
  • 一样

希望这有帮助, 最好的祝福, 汤姆。

答案 7 :(得分:2)

为什么你不应该这样做......

由于malloc的返回值是依赖于实现的,因此可能会返回NULL指针或其他一些地址。如果错误处理代码不检查大小和返回值,导致稳定性问题(崩溃)或甚至更严重的安全问题,这最终可能会导致堆缓冲区溢出。

考虑这个例子,如果大小为零,进一步通过返回的地址访问内存将损坏堆,并且实现返回非NULL值。

size_t size;

/* Initialize size, possibly by user-controlled input */

int *list = (int *)malloc(size);
if (list == NULL) {
  /* Handle allocation error */
}
else {
  /* Continue processing list */
}

请参阅CERT编码标准中的this Secure Coding page,我将上面的示例用于进一步阅读。

答案 8 :(得分:1)

要真正回答所提出的问题:没有理由这样做

答案 9 :(得分:0)

malloc(0)将返回NULL或一个可以正确传递给free的有效指针。虽然看起来它所指的内存是无用的,或者它无法写入或读取,但并非总是如此。 :)

int *i = malloc(0);
*i = 100;
printf("%d", *i);

我们期待这里出现分段错误,但令人惊讶的是,这会打印100个!这是因为当我们第一次调用malloc时,malloc实际上要求大量的内存。之后每次调用malloc都会使用来自那个大块的内存。只有在那个巨大的块结束后,才会要求新的记忆。

使用malloc(0):如果您希望后续malloc调用更快,则调用malloc(0)应该为您执行(边缘情况除外)。

答案 10 :(得分:0)

它实际上非常有用,并且(显然是恕我直言),返回NULL指针的允许行为已被破坏。动态指针不仅对它指向的内容有用,而且其地址是唯一的。返回NULL将删除该第二个属性。我编写的所有嵌入式malloc(实际上很多时候)都具有这种行为。

答案 11 :(得分:0)

在Windows中:

  • void *p = malloc(0);将在本地堆上分配零长度缓冲区。返回的指针是一个有效的堆指针。
  • malloc最终使用默认的C运行时堆调用HeapAlloc,然后调用RtlAllocateHeap等。
  • free(p);使用HeapFree释放堆上的0长度缓冲区。不释放它会导致内存泄漏。

答案 12 :(得分:-1)

不确定,根据我发现的一些random malloc source代码,输入为0会导致返回值为NULL。因此,将Artist指针设置为NULL是一种疯狂的方法。

http://www.raspberryginger.com/jbailey/minix/html/lib_2ansi_2malloc_8c-source.html

答案 13 :(得分:-2)

这是使用valgrind内存检查工具运行后的分析。

anything with the R8..R15 regs and parts thereof
anything that accesses the new 8 bit regs: DIL, SIL, BPL, SPL
anything that accesses 64 bit registers.

这是我的示例代码:

==16740== Command: ./malloc0
==16740==
p1 = 0x5204040
==16740==
==16740== HEAP SUMMARY:
==16740==     in use at exit: 0 bytes in 0 blocks
==16740==   total heap usage: 2 allocs, 2 frees, 1,024 bytes allocated
==16740==
==16740== All heap blocks were freed -- no leaks are possible

默认情况下,分配1024个字节。如果我增加malloc的大小,分配的字节将增加1025,依此类推。

答案 14 :(得分:-3)

根据Reed Copsey回答和malloc的手册页,我写了一些例子来测试。我发现malloc(0)总是给它一个独特的价值。 看我的例子:

char *ptr;
if( (ptr = (char *) malloc(0)) == NULL )
    puts("Got a null pointer");
else
    puts("Got a valid pointer");

输出将是"有一个有效的指针",这意味着ptr不为空。

答案 15 :(得分:-6)

只是为了纠正错误的印象:

artist = (char *) malloc(0);永远不会返回NULL;它与artist = NULL;不一样。编写一个简单的程序,并将artistNULL进行比较。 if (artist == NULL)为false,if (artist)为真。

答案 16 :(得分:-6)

malloc(0)将返回一个有效的内存地址,其范围将取决于正在分配内存的指针类型。您也可以为存储区分配值,但这应该在使用指针类型的范围内。您还可以释放分配的内存。我将用一个例子解释这个:

int *p=NULL;
p=(int *)malloc(0);
free(p);

上面的代码可以在Linux机器上的gcc编译器中正常工作。如果你有一个32位编译器,那么你可以提供整数范围内的值,即-2147483648到2147483647.同样适用于字符。请注意,如果声明的指针类型被更改,那么无论malloc类型转换,值的范围都会发生变化,即

unsigned char *p=NULL;
p =(char *)malloc(0);
free(p);

p将取0到255的char值,因为它被声明为unsigned int。