【问题标题】:Why does my program occasionally segfault when out of memory rather than throwing std::bad_alloc?为什么我的程序在内存不足而不是抛出 std::bad_alloc 时偶尔会出现段错误?
【发布时间】:2011-02-03 18:59:51
【问题描述】:

我有一个程序,它实现了几种启发式搜索算法和几个域,旨在通过实验评估各种算法。该程序用 C++ 编写,使用 GNU 工具链构建,并在 64 位 Ubuntu 系统上运行。当我运行我的实验时,我使用 bash 的 ulimit 命令来限制进程可以使用的虚拟内存量,这样我的测试系统就不会开始交换。

某些算法/测试实例组合达到了我定义的内存限制。大多数时候,程序会抛出一个 std::bad_alloc 异常,该异常由默认处理程序打印,此时程序终止。有时,程序不会发生这种情况,而是会出现段错误。

为什么我的程序在内存不足时偶尔会出现段错误,而不是报告未处理的 std::bad_alloc 并终止?

【问题讨论】:

  • 段错误不仅是因为你达到了内存限制
  • 我很清楚。在我看到段错误的情况下,该进程一直在使用接近我指定的限制的内存量。我非常确信我看到的段错误不是由于我的代码中的错误。
  • 您是否考虑过在 GDB 中简单运行(其中有几个)来查看代码的哪一部分出现段错误?

标签: c++ segmentation-fault bad-alloc


【解决方案1】:

一个原因可能是默认情况下 Linux 会过度使用内存。从内核请求内存似乎可以正常工作,但是稍后当您实际开始使用内存时,内核会注意到“哦,废话,我的内存不足”,调用内存不足 (OOM) 杀手,它会选择一些受害者进程并杀死它。

有关此行为的描述,请参阅http://lwn.net/Articles/104185/

【讨论】:

  • 可能。更多信息,我一直作为测试系统上的唯一用户运行,该系统具有 48GB 内存。我一直在运行 47GB 的虚拟内存 ulimit,它应该为操作系统留下足够的核心内存。链接到的文章来自 2004 年。它今天仍然有用吗?
【解决方案2】:

可能是一些代码使用 no-throw new 并且不检查返回值。

或者某些代码可能正在捕获异常,而不是处理它或重新抛出它。

【讨论】:

    【解决方案3】:

    janneb 说的。事实上 Linux 默认 从不 抛出 std::bad_alloc(或从 malloc() 返回 NULL)。

    【讨论】:

    • 我假设你的意思是“std::bad_alloc 在 Linux 上默认不会抛出”。那么,当程序达到其内存限制时,为什么我会在多个 Linux 系统上看到 C++ 程序抛出 std::bad_alloc?
    • 另外,我想你的意思是malloc' rather than free'。 malloc 的 Linux 手册页并没有让它听起来像 NULL 永远不会被返回。
    • 正如我所说,这是默认行为。看看这个线程:stackoverflow.com/questions/1592535/…
    • 我认为即使过度使用,如果你要求超过它知道它永远不可能满足的某个上限,或者如果你要求超过虚拟内存空间中剩余的部分,linux 确实会快速失败(我认为这在 64 位系统上非常罕见),或者超过在地址空间中连续保留的数量(同样,在 64 位系统上不会偶然发生)。我当然可能是错的。
    • @Steve 这是不久前的事了,但是 IIRC,在我的 x86_64 桌面上,有 8 GB RAM,我的简单测试程序分配了内存但从未触及它,能够在 malloc() 之前分配大约 90 GB返回 NULL。
    猜你喜欢
    • 2016-02-10
    • 1970-01-01
    • 2012-01-16
    • 2016-04-04
    • 2014-12-14
    • 1970-01-01
    • 2013-02-18
    相关资源
    最近更新 更多