【问题标题】:Malloc doesn't return NULLMalloc 不返回 NULL
【发布时间】:2016-05-24 13:34:55
【问题描述】:

我刚刚用一个巨大的内存请求测试了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;
}

【问题讨论】:

  • 请定义巨大,巨大不是一个精确的数量。
  • 你的意思是你不信任这个人?
  • 您向malloc 请求多少内存?贴出实际代码。系统可能会满足您对超出物理可用内存的请求,因为它可以使用交换文件来实现虚拟内存。
  • Huge 太模糊了。你需要多少内存?您的平台规格?
  • 还有,你用它做什么?只是int main(void) {void *pointer = malloc(CONSTANT_VALUE); if (pointer == NULL) printf("Cannot allocate 'Huge' bytes, sorry\n"); return 0;}?贴出代码。

标签: c memory malloc out-of-memory


【解决方案1】:

问题的原因有点棘手:

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);

此外,在您的计算机上分配 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。您可能有不同版本的工具和运行时库。

【讨论】:

  • 非常感谢!这解释了很多,你知道为什么这个问题被否决了吗?我做错了什么?我一开始没贴代码,就这样?
  • 实际上这里有 16GB 的内存,这很有可能,但该块无效。写入转向“段错误”,但操作数的更改修复了它。
猜你喜欢
  • 1970-01-01
  • 2015-06-14
  • 1970-01-01
  • 2017-06-18
  • 2012-11-18
  • 2015-12-03
  • 1970-01-01
  • 1970-01-01
  • 2011-03-31
相关资源
最近更新 更多