奇怪的std::bad_alloc

9
据我所知,std::bad_alloc可能会被抛出的原因有三个:
  1. 进程请求的内存超过了可用内存
  2. 地址空间过于分散,无法为大块连续内存提供服务
  3. 堆管理数据结构损坏
我们的代码遇到了std::bad_alloc异常,但似乎以上任何一个原因都不适用。该数据结构是作为顶点的std::list存储的图形,每个顶点再存储一些连续数据的边缘std::list。
对于小型图形(<= 100,000个顶点),程序运行得非常好,无论每个顶点的数据部分有多大(我们可以安全地分配总共高达40 GB的内存)。然而,如果顶点数量增加,即使使用“仅”8GB的内存,也会引发std::bad_alloc异常。
由于在分配更大的块内存时没有问题,因此排除了1和2的原因。我们有一些操作指针的区域,这种方式容易出错,因此我们可能会破坏堆数据结构。但是,在较小的实例上运行时,valgrind的memcheck显示我们的代码是完美的,因此这个原因也不太可能(在抛出异常的情况下,valgrind本身会耗尽内存,因此我们无法直接检查该情况)。
有什么其他原因可以解释这种行为的方法,或者我们可以运行什么测试以进一步确定问题?
操作系统:Fedora 19 构建系统:使用gcc 4.8.2的cmake

1
在计算时不要忘记内存管理器通常会为每个分配添加16-20字节。 - Billy ONeal
从技术上讲,bad_alloc 只会因为内存分配失败而被抛出。 - pmr
1
你可能需要关注有符号的大小。 - user2249683
你的大图可能有循环吗?你的顶点有多大?我假设这是一个64位可执行文件?你正在使用哪个库实现?顶点的构造函数是否进行了额外的分配?其中一个可能不正常吗?你尝试过任何分配跟踪工具吗? - Adrian McCarthy
@AdrianMcCarthy:不,这个图是一棵树。每个顶点都包含着std::list的边,三个指针,四个指向长度<=3的指针/整数的std::vectors和一个大小可变的double字段。后者的大小范围从单个数字到几百万个数字不等,bad_alloc出现在数据字段大小的两个极端(尽管对于较小的数据字段,树需要更大)。std库的实现是GNU ISO C++ Library,但我无法弄清楚版本(如何获取任何帮助?)。正如我所说,我试过了Valgrind's memcheck。 - gTcV
显示剩余13条评论
1个回答

6

我无法在您的帖子上进行评论,所以我会在回复中提出我的观点。

在使用OpenFST与Kaldi时(与您相同的系统和gcc版本),我遇到了同样的问题。我没有追踪这个问题的确切起源,但似乎3.12内核是引起问题的原因。我使用了备份内核之一(3.11系列之一)进行启动,问题就解决了。

您可以使用以下命令:

yum list --showduplicates kernel

查找可用的3.11内核。

编辑:

看起来,这个错误已经在Kernel 3.12.11-201和3.13+中得到了修复。

来源:Bugzilla


我们在一个不同的机器上运行了我们的代码,使用了3.10.11内核,它成功了!非常感谢您的提示,我们可能永远不会想到这可能是内核bug的问题! - gTcV
很高兴能帮忙,我也花了一些时间才到达那里 ;) - tvar0g

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接