关于C#:为什么malloc(0)在Windows中返回非空地址?

Why does malloc(0) return a non-null address in Windows?

下面的代码在Windows中执行时返回一个地址,尽管我希望它返回空值。

1
2
3
4
5
6
7
8
int main()
{
   char *ptr = NULL;
   ptr = malloc(0);
   printf("malloc returned = %u
"
, ptr);

}

是什么促使了malloc的实施?背后有什么原因吗?

因为这是一个0字节的内存,所以我没有尝试写入任何数据。但是,这个记忆可以用来做任何事情吗?


这只是你要的最小尺寸。而且由于在win32堆中没有零长度块,您可以:

1
2
3
void *p = malloc(0);
// ... do some stuff in between...
realloc(p, n);

这通常会导致重用堆中的一个块(如果幸运的话,并且新的大小很小)。一个小的机会主义优化(或一个慢下来,取决于上下文和血咖啡水平)。

这是一个简单的例子。实际情况可以是一个类,它在创建缓冲区时分配缓冲区,并允许缓冲区增长。如果输入控制起来很烦人,您可以让它进行零大小的缓冲区分配。


要回答问题"否"的第二部分,内存不能用于任何事情,因为"它的可访问部分"是从返回的地址开始的0字节。

IIRC虽然保证如果实现返回非空值,那么它将是与当前分配的任何其他内存块不同的地址。因此,理论上,您可以将地址用作临时唯一ID(指针类型),尽管显然有许多其他方法可以获得唯一ID。即使您打算使用它,malloc(1)也可以与malloc(0)一样工作,并且更易于移植。


在comp.lang.c FAQ:http://c-faq.com/ansi/malloc0.html中回答了这个问题。

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.


标准规定它可以

http://pubs.opengroup.org/onlinepubs/009695399/functions/malloc.html


它不是无用的。从malloc返回的块应该是唯一的。因此,malloc返回的每个块都携带块内的数据和它的唯一标识符,即它的地址。如果后一个属性很重要,并且它不包含数据这一事实不是问题,那么它是有用的。

但是,正如前面提到的,它是编写不可移植代码的一种很好的方法。但是,这与非法代码不同,而且实现支持它是完全有效的(显然Windows支持)。