程序以std::bad_alloc终止 < >我运行一个C++程序,它在任意点上以代码> STD::BADYOLLC/死亡,这取决于指定的输入。以下是关于该计划的一些观察/观点: 对于较短的运行(运行时间取决于输入),程序正常完成。这个问题只适用于更大的跑步 该程序没有任何可检测的内存泄漏。通过Valgrind/Memcheck对较小的运行进行检查。此外,我的整个代码没有任何指针(所有动态分配都由库完成,例如在std::vector和std::string中;这些库类中的分配失败),因此内存泄漏的可能性极低 几个对象在循环中分配,然后移动到容器中。这些对象中有几个将一直处于活动状态,直到程序几乎结束 我怀疑堆碎片可能是一个问题(请参阅),但我在使用64位编译器的64位系统上(特别是使用g++的Linux),这让我相信在64位系统上堆碎片不会是一个问题

程序以std::bad_alloc终止 < >我运行一个C++程序,它在任意点上以代码> STD::BADYOLLC/死亡,这取决于指定的输入。以下是关于该计划的一些观察/观点: 对于较短的运行(运行时间取决于输入),程序正常完成。这个问题只适用于更大的跑步 该程序没有任何可检测的内存泄漏。通过Valgrind/Memcheck对较小的运行进行检查。此外,我的整个代码没有任何指针(所有动态分配都由库完成,例如在std::vector和std::string中;这些库类中的分配失败),因此内存泄漏的可能性极低 几个对象在循环中分配,然后移动到容器中。这些对象中有几个将一直处于活动状态,直到程序几乎结束 我怀疑堆碎片可能是一个问题(请参阅),但我在使用64位编译器的64位系统上(特别是使用g++的Linux),这让我相信在64位系统上堆碎片不会是一个问题,c++,memory-management,C++,Memory Management,还有什么我应该试试的吗?有什么特别的工具可以帮助你吗?还有其他建议吗 更新:最终证明虚拟内存在早些时候通过ulimit-v受到了限制。后来我忘了这件事,因此我的记忆力很差。将其设置回unlimited修复了该问题。std::bad\u alloc表示您请求的内存超过了可用内存 您可能会遇到这样的情况:程序没有泄漏,但仍然真正耗尽内存: vector<long> v; long n = 0; for(;;) { v.push_back(n++); } 向量v; 长n=0; 对于

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


更新:最终证明虚拟内存在早些时候通过
ulimit-v
受到了限制。后来我忘了这件事,因此我的记忆力很差。将其设置回
unlimited
修复了该问题。

std::bad\u alloc
表示您请求的内存超过了可用内存

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

vector<long> v;
long n = 0;
for(;;)
{
   v.push_back(n++);
}
向量v; 长n=0; 对于(;;) { v、 推回(n++); } 最终将耗尽您拥有的任何机器中的所有可用内存-但它不会泄漏-所有内存都将计入向量中。显然,任何容器都可以做完全相同的事情,
向量
列表
映射
,其实并不重要

Valgrind只查找您“放弃”分配的实例,而不查找您正在使用当前可访问内存填充系统的实例

可能发生的情况是上述情况的一种更慢的形式——您正在某个容器中存储越来越多的内容。它可能是您正在缓存的内容,也可能是您认为已将其删除时未删除的内容

观察应用程序上的内存量在某些监控程序中实际使用(“Linux/Unix中为top”,Windows中为task manager”),并查看它是否实际增长。如果是这样的话,那么你需要弄清楚什么在增长——对于一个大型程序来说,这可能很棘手(有些东西可能会增长,而有些东西不会……)

当然,您也可能突然得到一些糟糕的计算结果,例如,在
T*p=newt[elements]中要求使用负数的元素
将导致错误的alloc,因为元素被转换为无符号,并且负无符号数非常大

如果您可以在调试器中捕获错误的alloc,那么这类事情通常很容易发现,因为
new
请求的大量内容将非常明显

在调试器中捕获异常通常会有所帮助,尽管当一个小字符串出错时,您可能只是在为它分配内存,但如果您确实有泄漏的内容,那么当它出错时,这就是分配内存的内容,这并不奇怪


如果您使用的是Unix风格,为了加快错误查找,还可以使用
ulimit-m size
(以千字节为单位)或
ulimit-v size
,将允许应用程序使用的内存量设置为较小的大小

std::bad_alloc
也可能意味着您请求的数据量为负数,即使计算机内存充足

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

例如,假设您希望在21维空间中分配1亿个点。没问题。计数为210000000。现在将维度大小增加到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:我在评论中注意到这似乎是一个不可复制的结果,因为现在新的[count]在重启机器后给出了
std::bad\u array\u new\u length
。也就是说,代码仍然不正确并中断,但给出的错误消息与以前不同。在任何情况下都不要这样做。

检查基本堆栈损坏、缓冲区溢出或错误返回。这些都是valgrind会错过的,并且可能导致腐败问题。我同意,在这方面我做不了多少。你有什么我可以试试的工具吗?我通常是手工做的,获得一些线索的简单方法是将它加载到gdb中,一旦它碰到坏的东西,就返回堆栈,检查垃圾值是多少以及它可能来自哪里谢谢!这个问题有点幼稚。几天前,我将虚拟内存限制在4GB左右(通过
ulimit-v
——你的回答提醒了我!)。现在,我在同一个终端上运行这个程序,忘记了这个设置,也就忘记了这个问题。将其设置为“无限制”会使事情变得正确。正如我在问题中所说,使用64位系统而不使用指针意味着您指出的其他问题不太可能出现。也许这个问题和答案将来会帮助别人!如果您不使用指针[间接地,例如通过
std::vector
,可能),您就不会得到
std::bad\u alloc