为什么 malloc(LLONG_MAX) 会抱怨,而 malloc(ULLONG_MAX) 却不会?

问题描述 投票:0回答:1

案例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)

c malloc
1个回答
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
字节,则可能就是这个意思。)

© www.soinside.com 2019 - 2024. All rights reserved.