Malloc 不返回 NULL

Las*_*ive 3 c memory malloc out-of-memory

我刚刚测试malloc了一个巨大的内存请求,但它没有返回NULL。我已经听说过这个,但是 BSD(我在 mac 上)手册页说:

返回值
如果成功,calloc()malloc()realloc()reallocf()valloc()函数返回一个指向已分配内存的指针。如果有错误,它们返回一个NULL指针并将 errno 设置为ENOMEM

如何正确且可靠地检查返回的指针是否指向请求大小的有效块?

编辑:我刚看到这篇文章。我猜 BSD 也一样?

编辑2:代码:

typedef struct {
    uint8_t red;
    uint8_t green;
    uint8_t blue;
} RGB_TYPE;

int main() {
    RGB_TYPE *field = malloc(50000 * 50000 * sizeof(RGB_TYPE));

    if (!field)
        return -1;

    ... write to field (SEG_FAULT) ... 

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

chq*_*lie 5

您的问题的原因有点棘手:

50000*50000*sizeof(RGB_TYPE)被评估为(size_t)(50000 * 50000) * sizeof(RGB_TYPE)。乘法从左到右关联,所以第一次乘法是用int算术和溢出来执行的,因为2500000000它比INT_MAX你的平台上的大。

整数溢出会调用未定义的行为,并且您的平台 ( clang) 可能会在这种情况下生成愚蠢的代码。如果指示(clang -Wallclang -Weverything),它可以产生诊断。在任何情况下,您的代码都会崩溃,因为数组没有预期的大小。

将代码更改为

RGB_TYPE *field = malloc(sizeof(RGB_TYPE) * 50000 * 50000);
Run Code Online (Sandbox Code Playgroud)

此外,可以在您的计算机上分配 7.5 GB 的内存。这将取决于系统配置,但即使您只有 8GB 的​​ RAM,OS/X 也允许这样做并非不现实。

编辑: 在我的 Mac 上,您的代码确实不会产生警告clang -Weverything,这是一个真正的麻烦,并尝试分配18446744068324649728字节。我从malloc以下位置收到运行时警告:

malloc-test(53877,0x7fff79dbe000) malloc: 
   *** mach_vm_map(size=18446744068324651008) failed (error code=3)
   *** error: can't allocate region
   *** set a breakpoint in malloc_error_break to debug
Run Code Online (Sandbox Code Playgroud)

malloc返回NULL。您可能拥有不同版本的工具和运行时库。