案例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)
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
字节,则可能就是这个意思。)