问题 为什么我的程序在内存不足时偶尔会出现段错误而不是抛出std :: bad_alloc?


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

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

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


2894
2018-04-02 16:07


起源

可能导致段错误不仅仅是因为你达到了内存限制 - Andrey
我很清楚。在我看到段错误的情况下,该进程一直使用接近我指定限制的内存量。我非常有信心我看到的段错误不是由于代码中的错误造成的。 - Bradford Larsen
您是否考虑过在GDB(以及其中一些)中进行简单运行,以查看代码的哪一部分出错? - Shiroko


答案:


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

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


8
2018-04-02 16:16



有可能。更多信息,我一直作为测试系统上唯一的用户运行,它有48GB的内存。我一直在运行47GB虚拟内存ulimit,这应该为操作系统留下足够的核心内存。链接文章来自2004年。它今天仍然有用吗? - Bradford Larsen


什么janneb说。实际上Linux默认情况下 决不 抛出std :: bad_alloc(或从malloc()返回NULL)。


1
2018-04-02 16:39



我假设你的意思是“在Linux上默认情况下不会抛出std :: bad_alloc”。那么,当程序达到内存限制时,为什么我会在几个Linux系统上看到从C ++程序抛出的std :: bad_alloc? - Bradford Larsen
另外,我认为你的意思 malloc' rather than 自由'。 malloc的Linux手册页不会让它听起来像永远不会返回NULL。 - Bradford Larsen
@Bradford。你当然是对的。固定。 - Nemanja Trifunovic
正如我所说,这是默认行为。看看这个帖子: stackoverflow.com/questions/1592535/... - Nemanja Trifunovic
我认为,即使过度使用,如果你要求超过某个上限它知道它永远不可能满足,或者如果你要求的数量远远超过虚拟内存空间(这是非常罕见的一个64位系统,我想),或者更多可以在地址空间中连续保留(再次,不会在64位系统上偶然发生)。我当然错了。 - Steve Jessop


它可能是一些使用no-throw new的代码,而不是检查返回值。

或者一些代码可以捕获异常而不处理它或重新抛出它。


1
2018-04-02 17:27