我一直在阅读有关malloc
在请求零尺寸块时的行为的讨论。
我了解malloc(0)
的行为是实现定义的,应该返回null指针,或或是我不应该访问的非弹药指针。(这是有道理的,因为不能保证它指向任何可用的内存。(
但是,如果a获得这样的不可访问的非挂钩指针,我是否允许以通常的方式将其传递给free
?还是那是非法的,因为我从malloc(0)
获得的指针可能无法指向实际分配的内存块?
具体而言,以下代码具有明确的行为:
#include <stdio.h>
#include <stdlib.h>
int main() {
int* x = (int*) malloc(0);
if (x == NULL) {
printf("Got NULLn");
return 0;
} else {
printf("Got nonnull %pn", x);
}
free(x); // is calling `free` here okay?
}
C99标准(实际上是WG14/N1124。委员会草案 - 2005年5月6日。ISO/IEC 9899:TC2(关于malloc()
:
指针返回点开始(最低字节 分配空间的地址(。如果无法分配空间,则无效指针是 回。如果所请求的空间的大小为零,则该行为是定义的: 返回了无效指针,或者行为是大小是某些大小 非零值,除了返回的指针不得用于访问对象
和关于 free()
:
否则,如果 该参数不匹配calloc,malloc或realloc函数返回的指针,或者如果空间已被呼叫呼叫免费或realloc,则行为是未定义的。
IEEE STD 1003.1-2008(POSIX(,2016年版有关free()
:
free((函数应导致PTR指向的空间为 交易;也就是说,可用于进一步分配。如果是PTR 无效指针,不会采取任何行动。否则,如果论点确实 不匹配POSIX的函数返回的指针。1-2008 这将记忆好像通过malloc((或空间已经 由free((或realloc((的呼叫所划分的行为是 未定义。
所以,无论*alloc()
返回,您都可以传递给free()
。
对于malloc()
的当前实现:
freeBSD使用
的贡献的jemallocvoid *
je_malloc(size_t size)
{
void *ret;
size_t usize JEMALLOC_CC_SILENCE_INIT(0);
if (size == 0)
size = 1;
[...]
苹果的libmalloc确实
void *
szone_memalign(szone_t *szone, size_t alignment, size_t size)
{
if (size == 0) {
size = 1; // Ensures we'll return an aligned free()-able pointer
[...]
GLIBC还更改了所需的大小;它正在使用对此宏的调用,其中所需的大小是字节中的参数,以使大小与特定边界对齐或最小分配大小:
#define request2size(req)
(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ?
MINSIZE :
((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
是的,实际上,您必须这样做才能避免可能的内存泄漏。
Malloc系统通常在指针前的空间中返回一个隐藏的控制块,并带有分配尺寸之类的信息。如果分配大小为零,则此块仍然存在并占据内存,如果Malloc返回非零件。