【问题标题】:Memory allocation fails. But why does it crash? Or does it?内存分配失败。但为什么会崩溃?或者是吗?
【发布时间】:2015-11-05 15:52:36
【问题描述】:

我在试验realloc,给它越来越大的尺寸,并检查同一个块是否被重用:

int main ( void )
{
  char * newstr, * prevstr = NULL;
  size_t newsize, prevsize = 0;
  printf ("We play with realloc\n");
  while (1) {
    newsize = prevsize + 1 + prevsize/3; /* add 33% */
    newstr = realloc(prevstr, newsize);
    if (newstr == NULL) {
      printf ("could not alloc newsize=%zu. Sorry\n", newsize);
      break;
    } else {
      printf ("newsize=%zu successfully alloc'ed\n", newsize);
      if (newstr == prevstr) {
        printf ("newstr = prevstr:\tSame block reused\n");
      } else {
        printf ("newstr != prevstr:\tNew block alloc'ed\n");
      }
      prevstr = newstr; prevsize = newsize;
    }
  }
  return (EXIT_SUCCESS);
}

正如预期的那样,最终会达到尺寸太大而realloc 无法响应请求的地步。根据手册,realloc 不成功时应该返回NULL 并设置errno = ENOMEM

当我在我的机器上运行上述代码时不会发生这种情况,这是一台带有“Darwin Kernel Version 15.0.0”的 Mac。 代码没有返回NULL,而是崩溃并说

malloc: *** mach_vm_map(size=153288611651584) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
could not alloc newsize=153288611651277. Sorry

这正常吗?阅读手册页时有什么我不明白的地方?

目前这对我的代码来说并不重要,但我可以想象在哪些情况下我想测试是否可以分配内存而不会有崩溃的风险。有没有一种标准的方法来测试 alloc 是否可以工作而不会冒这种崩溃的风险?

解开谜团后添加(见下面的答案):没有崩溃,只是一些来自 malloc 的系统错误消息妨碍了预期的输出。请参阅下文,了解如何避免这种情况。

【问题讨论】:

  • 这里好像有些东西不符合标准..
  • 它似乎并没有真正崩溃。它只是输出一些额外的诊断信息并返回 NULL(当newstr == NULL 时,您的代码会打印消息“无法分配新大小”)。
  • 好点。真的会崩溃吗?
  • 我相信它会转到stderr,你可以重定向它。或者甚至使用一些宏将其关闭。类似here
  • @Kevin 是的。 C11 6.2.4p2:“当指针指向(或刚刚过去)的对象到达其生命周期的尽头时,指针的值变得不确定”。 “不确定值”在 3.19.2 中定义为可能有效。 (基本上听起来像 C 不遗余力地允许 malloc &c. 重用位置,而无需 GC 所有对它们的引用。)因此允许比较本身(6.5.9 中没有 UB),但不能保证产生有意义的结果。

标签: c memory-management malloc


【解决方案1】:

正如 cmets 所说,分配失败不会导致崩溃,只有错误消息。

如果该消息让您烦恼,您可以通过将malloc 的日志重定向到/dev/null 来关闭它,如下所示:

export MallocLogFile=/dev/null

设置环境变量前的输出如下:

newstr = prevstr:   Same block reused
a.out(4275,0x7fff7146e000) malloc: *** mach_vm_map(size=153288611651584) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
could not alloc newsize=153288611651277. Sorry

设置变量后输出如下:

newstr = prevstr:   Same block reused
could not alloc newsize=153288611651277. Sorry

注意:这是高度特定于 Mac 的。有关调整 malloc 操作细节的其他环境变量的描述,请参阅 documentation

【讨论】:

    【解决方案2】:

    代码没有因为“无法分配 newsize=153288611651277。抱歉”输出而崩溃 - 只是打印了一条附加消息。 @Blagovest Buyukliev

    附加消息很可能发送到stderr 而不是stdout@Eugene Sh.

    【讨论】:

    • 谢谢大家。愚蠢的谜团解开了。这里的 SE 政策是什么?我应该删除问题吗?编辑它(但要说什么?)?
    • @phs 没有理由删除人们觉得有趣的问题(从投票计数中可以看出)。您可能想要编辑标题以不谈论 malloc 崩溃,而是谈论隐藏消息。
    • @phs 建议离开。 1)这是一个很好的问题。 2)它演示了错误消息(stderr)混淆正常输出stdout的问题。 3) 我喜欢realloc() 演示代码为commented
    • @phs - “错误”问题通常比“正确”问题更具教育意义,因为其他人可能会遇到同样的问题。人们很少发帖说“为什么它完全按照我的预期工作”,所以看到诸如“为什么它不能正常工作”之类的问题很有用,即使事实证明它工作正常,但显然不是这样。
    猜你喜欢
    • 2012-07-04
    • 1970-01-01
    • 2012-05-09
    • 2014-05-31
    • 1970-01-01
    • 2010-11-14
    • 1970-01-01
    • 2016-10-09
    • 1970-01-01
    相关资源
    最近更新 更多