案例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)
答案 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
字节,则可能意味着它。)