为什么malloc(LONG_MAX)抱怨但malloc(ULLONG_MAX)没有?

时间:2014-05-20 19:22:02

标签: c malloc

案例1:

#include <stdlib.h>
#include <limits.h>

int main()
{
    void *mem = malloc(ULLONG_MAX); /* or ULONG_MAX */

    return 0;    
}

案例2:

#include <stdlib.h>
#include <limits.h>

int main()
{
    void *mem = malloc(LLONG_MAX); /* or LONG_MAX */

    return 0;    
}

两种情况都返回一个NULL指针,并按预期将errno设置为12(ENOMEM)。但在后者中,它实际上抱怨内存不足:

long(5072) malloc: *** mmap(size=9223372036854775808) failed (error code=12) *** error: can't allocate region *** set a breakpoint in malloc_error_break to debug

我只是好奇为什么会发生这种情况,因为ULLONG_MAX大于LONG_MAX

系统是Mac OS X 10.8.5,Apple LLVM 5.1版(clang-503.0.40)

1 个答案:

答案 0 :(得分:3)

malloc的参数类型为size_t,这是一种无符号类型。

mmap失败的错误消息中,很明显您的malloc正在使用64位大小。实际上,您的size_t很可能与unsigned long long的类型相同。

换句话说,它可以表示ULLONG_MAX值而不会溢出。它也可以代表LLONG_MAX值,大约是它的一半。

您的malloc函数可能包含一些安全保护逻辑,当它被要求提供2 ** 64-1字节时,它会阻止它实际发出mmap请求;它甚至只是在没有尝试分配内存的情况下发生故障。但是当“仅”要求2 ** 63-1字节时,它会发出mmap,因此请求在内核中失败,从而导致内核日志消息。

您可能还想尝试malloc(ULLONG_MAX - 1)来查看安全措施是否仅适用于最高可能的64位无符号值,或者是否从那里扩展到更低的范围。

malloc拒绝接近最大值size_t的一系列大小是有意义的,因为这些大小可能是导致环绕的计算错误的结果。

(当然,在size_t为16位的小型系统上,malloc不能这样做:如果程序要求65535字节,则可能意味着它。)