我刚用一个巨大的内存请求测试malloc
,但它没有返回NULL
。我已经听说过这个但是BSD(我在Mac上)man-page说:
返回值
如果成功,calloc()
,malloc()
,realloc()
,reallocf()
和valloc()
函数将返回指向已分配内存的指针。如果 如果出现错误,则返回NULL
指针并将errno设置为ENOMEM
。
如何正确可靠地检查返回的指针指向请求大小的有效块?
编辑:我刚看到this帖子。对于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;
}
答案 0 :(得分:4)
问题的原因有点棘手:
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);
此外,您的计算机上可能会分配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
和malloc
返回NULL
。您可能拥有不同版本的工具和运行时库。