我正在运行一个C ++程序,它在任意点死于std::bad_alloc
,这取决于指定的输入。以下是关于该计划的一些观察/观点:
std::vector
和std::string
;这些库类中的分配失败了),因此内存泄漏非常不可能。还有什么我应该尝试的吗?任何可以帮助的特定工具?还有其他建议吗?
更新:最后证明虚拟内存早先被ulimit -v
限制。我后来忘了这件事,因此内存耗尽。将其重新设置为unlimited
可解决问题。
答案 0 :(得分:5)
std::bad_alloc
表示您请求的内存比可用内存多。
您可以遇到程序没有泄漏但仍然真正耗尽内存的情况:
vector<long> v;
long n = 0;
for(;;)
{
v.push_back(n++);
}
最终将耗尽你所拥有的任何机器中的所有可用内存 - 但它不会泄漏 - 所有内存都在向量中占用。显然,任何容器都可以做同样的事情,vector
,list
,map
,并不重要。
Valgrind只找到你“放弃”分配的实例,而不是用当前可达内存填充系统的地方。
正在发生的是一种较慢的形式 - 你在一些容器中存储的越来越多。它可能是您正在缓存的内容,或者您认为已删除它时未删除的内容。
观察应用程序上的内存量实际上是在一些监控程序中使用(Linux / Unix中的“top”,Windows中的“任务管理器”)并查看它是否实际增长。如果是这种情况,那么你需要弄清楚正在发展的是什么 - 对于一个大型项目来说,这可能很棘手(有些事情可能会成长,有些则不会......)
当然,您可能会突然得到一些不好的计算,例如:在T* p = new T[elements];
中要求负数的元素会导致错误的分配,因为元素被转换为无符号,而负无符号数是巨大的。
如果您可以在调试器中捕获bad_alloc,那么通常很容易发现这种情况,因为new
请求的大量数据将非常明显。
在调试器中捕获异常应该是一般的帮助,虽然当然可能你只是在出错时为一个小字符串分配内存,如果你确实有泄漏的东西,这就是这个并不罕见当它出错时分配。
如果您正在使用Unix的风格,您还可以使用ulimit -m size
(以千字节为单位)或者加速错误查找,将应用程序允许使用的内存量设置为较小的大小。 ulimit -v size
。
答案 1 :(得分: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
插入,因为请求的内存计数为负。
Ed .:我在评论中指出这似乎是无法再现的结果,因为现在new [count]在重启机器后给出了std::bad_array_new_length
。也就是说,代码仍然不正确并且会中断,但是给出的错误消息与以前不同。无论哪种情况都不要这样做。