c - 为什么 malloc(LONG_MAX) 会提示,而 malloc(ULLONG_MAX) 却不会?

标签 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) 失败(错误代码=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/

相关文章:

c - 在 C 中使用 strstr 在主字符串中搜索多个字符串

c - 在 C 中,是否可以只释放数组的第一个或最后一个位置?

c - 如果我使用 mmap 而不是 malloc 分配内存会怎样?

c - C 是否有使用 malloc 初始化结构并设置其字段的简写方法?

c - 在 C 中返回动态分配的结构时出现未处理的异常

c - windows内核编程中如何使用线程?

c - 为什么复制内存时出现段错误

c - 使用 malloc() 和 free() 函数时出错

c++ - 使用 malloc 进行动态内存分配

c - C中局部变量的返回地址