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)
您的问题的原因有点棘手:
50000*50000*sizeof(RGB_TYPE)
被评估为(size_t)(50000 * 50000) * sizeof(RGB_TYPE)
。乘法从左到右关联,所以第一次乘法是用int
算术和溢出来执行的,因为2500000000
它比INT_MAX
你的平台上的大。
整数溢出会调用未定义的行为,并且您的平台 ( clang
) 可能会在这种情况下生成愚蠢的代码。如果指示(clang -Wall
或clang -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
。您可能拥有不同版本的工具和运行时库。