案例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) 失败(错误代码=12)
*** 错误:无法分配区域
*** 在malloc_error_break中设置断点进行调试
我只是好奇为什么会发生这种情况,因为 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
字节,大概就是这个意思。)
关于c - 为什么 malloc(LONG_MAX) 会提示,而 malloc(ULLONG_MAX) 却不会?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23768225/