我正在运行一个C ++程序,该程序在任意点处都以std::bad_alloc
终止,具体取决于指定的输入。以下是有关程序的一些观察点/要点:
std::vector
和std::string
中;正是这些库类内部的分配失败),因此内存泄漏极不可能发生。 还有其他我应该尝试的东西吗?有什么特别的工具可以帮助您吗?还有其他建议吗?
更新:最终结果是,虚拟内存之前已通过ulimit -v
受到限制。后来我忘记了这一点,因此内存耗尽。将其设置回unlimited
可解决此问题。
[std::bad_alloc
意味着您请求的内存超出了可用的内存。
您可能会遇到程序没有泄漏但仍然真正耗尽内存的情况:
vector<long> v;
long n = 0;
for(;;)
{
v.push_back(n++);
}
最终将耗尽您拥有的任何计算机上的所有可用内存-但它不会泄漏-所有内存都在向量中占了。显然,任何容器都可以做完全相同的事情,vector
,list
,map
并不重要。
Valgrind仅找到您“放弃”分配的实例,而不是您用当前可访问的内存填充系统的实例。
很可能正在发生的是上述形式的较慢形式-您将越来越多的内容存储在某个容器中。它可能是您正在缓存的东西,或者当您以为已删除它时并未将其删除。
观看应用程序中的内存量实际上正在某些监控程序中使用(在Linux / Unix中为“ top”,在Windows中为“ task manager”),并查看其是否在实际增长。如果真是这样,那么您需要弄清楚正在增长的东西-对于大型程序,这可能会很棘手(某些事情可能应该增长,而其他事情则不应...)
当然,您也可能突然得到一些错误的计算,例如要求T* p = new T[elements];
中的元素数为负数会导致分配错误,因为元素被转换为无符号数,并且负无符号数非常大。
如果您可以在调试器中捕获bad_alloc,通常很容易发现这种情况,因为new
要求的数量非常明显。
在调试器中捕获异常通常应该有所帮助,尽管当然有可能在出现错误时只是为一个小字符串分配内存,如果确实有泄漏的内容,这是正常的。出错时进行分配。
[如果您使用的是Unix,也可以使用ulimit -m size
(以千字节为单位)或ulimit -v size
来设置允许应用程序使用的较小内存,以加快错误查找速度。 。
[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。