程序终止于std :: bad_alloc

问题描述 投票:5回答:2

我正在运行一个C ++程序,该程序在任意点处都以std::bad_alloc终止,具体取决于指定的输入。以下是有关程序的一些观察点/要点:

  • 对于较短的运行(运行时间取决于输入),程序将正常完成。该问题仅适用于较大的运行。
  • 该程序没有任何可检测的内存泄漏。使用Valgrind / Memcheck进行了较小的运行检查。而且,我的整个代码没有任何指针(所有动态分配都是由库完成的,例如,在std::vectorstd::string中;正是这些库类内部的分配失败),因此内存泄漏极不可能发生。
  • 几个对象被循环分配,然后移到容器中。这些对象中的几个对象将一直存在,直到程序几乎结束。
  • [我怀疑堆碎片可能是一个问题(请参阅C++ program dies with std::bad_alloc, BUT valgrind reports no memory leaks),但是我在具有64位编译器(尤其是Linux和g ++的64位系统)上,并且Heap fragmentation in 64 bit land使我相信堆碎片不能成为64位系统上的问题。

还有其他我应该尝试的东西吗?有什么特别的工具可以帮助您吗?还有其他建议吗?

更新:最终结果是,虚拟内存之前已通过ulimit -v受到限制。后来我忘记了这一点,因此内存耗尽。将其设置回unlimited可解决此问题。

c++ memory-management
2个回答
6
投票

[std::bad_alloc意味着您请求的内存超出了可用的内存。

您可能会遇到程序没有泄漏但仍然真正耗尽内存的情况:

vector<long> v;
long n = 0;
for(;;)
{
   v.push_back(n++);
}

最终将耗尽您拥有的任何计算机上的所有可用内存-但它不会泄漏-所有内存都在向量中占了。显然,任何容器都可以做完全相同的事情,vectorlistmap并不重要。

Valgrind仅找到您“放弃”分配的实例,而不是您用当前可访问的内存填充系统的实例。

很可能正在发生的是上述形式的较慢形式-您将越来越多的内容存储在某个容器中。它可能是您正在缓存的东西,或者当您以为已删除它时并未将其删除。

观看应用程序中的内存量实际上正在某些监控程序中使用(在Linux / Unix中为“ top”,在Windows中为“ task manager”),并查看其是否在实际增长。如果真是这样,那么您需要弄清楚正在增长的东西-对于大型程序,这可能会很棘手(某些事情可能应该增长,而其他事情则不应...)

当然,您也可能突然得到一些错误的计算,例如要求T* p = new T[elements];中的元素数为负数会导致分配错误,因为元素被转换为无符号数,并且负无符号数非常大。

如果您可以在调试器中捕获bad_alloc,通常很容易发现这种情况,因为new要求的数量非常明显。

在调试器中捕获异常通常应该有所帮助,尽管当然有可能在出现错误时只是为一个小字符串分配内存,如果确实有泄漏的内容,这是正常的。出错时进行分配。

[如果您使用的是Unix,也可以使用ulimit -m size(以千字节为单位)或ulimit -v size来设置允许应用程序使用的较小内存,以加快错误查找速度。 。


1
投票

[std::bad_alloc也可能意味着您正在请求负数的数据,即使计算机中有足够的内存。

这种情况在我的64位linux机器上很容易发生,当我使用常规的有符号整数(仍为32位)而不是长整数(64位)来指定数组计数时,我将两个数字相乘太大而无法获得最终数量。乘法结果在2.147Gig处安静地溢出,因此可能变为负数。

例如,您想在21维空间中分配1亿个点。没问题。计数是2,100,000,000。现在将尺寸尺寸增加到22,它会从悬崖上掉下来。这很容易通过printf验证:

int N = 100000000;
int D = 22;
int count = N * D;
printf("count = %'d\n", count);

给予

count = -2,094,967,296

std::bad_alloc插入,因为请求的内存计数为负。

编辑:我在评论中注意到这似乎是不可复制的结果,因为现在new [count]给出std::bad_array_new_length。 YMMV。

© www.soinside.com 2019 - 2024. All rights reserved.