ISO/IEC 9899:TC2(即C99标准)第7.20.3节规定:
如果请求空间的大小为零,则行为是实现定义的:要么返回空指针,要么行为就像大小为非零值一样,除了不能使用返回的指针来访问对象。
换句话说,malloc(0)可能会返回NULL,也可能会返回一个有效的指针,但不能对其进行引用。
这种行为背后的原理是什么?
难道直接定义malloc(0)会导致未定义行为不更容易吗?
ISO/IEC 9899:TC2(即C99标准)第7.20.3节规定:
如果请求空间的大小为零,则行为是实现定义的:要么返回空指针,要么行为就像大小为非零值一样,除了不能使用返回的指针来访问对象。
换句话说,malloc(0)可能会返回NULL,也可能会返回一个有效的指针,但不能对其进行引用。
这种行为背后的原理是什么?
难道直接定义malloc(0)会导致未定义行为不更容易吗?
C99 Rationale(PDF链接)讨论了内存管理函数(来自C99 7.20.3)并解释说:
在这些函数的定义中,对空指针和零长度分配请求的处理部分受到希望支持此范例的影响:
OBJ * p; // pointer to a variable list of OBJs /* initial allocation */ p = (OBJ *) calloc(0, sizeof(OBJ)); /* ... */ /* reallocations until size settles */ while(1) { p = (OBJ *) realloc((void *)p, c * sizeof(OBJ)); /* change value of c or break out of loop */ }
报告称,这种编码风格虽然不一定得到委员会的认可,但却被广泛使用。
有些实现在分配零字节的请求时会返回非空值。
尽管这种策略具有区分“无”和“零”的理论优势(未分配指针与指向零长度空间的指针之间的区别),但它具有更为强制性的理论缺点,需要引入零长度对象的概念。由于这样的对象不能被声明,它们唯一存在的方式是通过这样的分配请求。
C89委员会决定不接受零长度对象的想法。因此,分配函数可能会对零字节的分配请求返回一个空指针。请注意,这种处理方式并不排除上述范例。
C89中的悄悄变化:依赖于大小为零的分配请求返回非空指针的程序将表现出不同的行为。
numberOfItems * itemSize
字节。malloc(0)
定义为UB的原因。关于决定不严格定义结果(NULL
vs.唯一指向空间的指针),请参见James的答案。(简而言之:两种方法都有优缺点。返回唯一的非空指针的想法更具说服力,但需要更多的概念工作,并对实现者施加更大的负担。)realloc
调整大小为零并返回指向最小分配的指针,则在随后使用相同指针进行非零大小请求时能够重用相同空间(如果仍然可用),这种情况有时可能是有利的;如果realloc
可以为大小为零的请求返回非空值,则允许malloc
也可以这样做是有意义的。 - supercatmalloc(0)
的结果为未定义行为会更糟。目前,只要您在调用free
时保持一致,就不必关心大小为零时会发生什么。malloc(0)
分配指针,一些返回空指针,几乎所有这些实现都坚决坚持自己的行为,因为编写这些实现的人编写了大量糟糕的、不可移植的软件,这些软件使用了他们选择的行为(GNU在这方面是最严重的罪犯之一)。因此,标准被卡住了,允许两种行为以使所有人都满意。malloc(0)
,如果没有,则会进行可怕的包装处理。 - R.. GitHub STOP HELPING ICE