在写一篇关于欧拉项目第 14 个问题的帖子时,我遇到了 VC9 和 VC10 之间的行为差异。
以下代码在 VC9 中运行正常,但在 VC10 中std::unordered_map
抛出bad_alloc
异常。奇怪的是,如果我从异常中恢复,未来的分配将成功(容器的大小继续增长)。此外,如果我使用boost::unordered_map
它在两个编译器中都可以正常工作。
关于实际内存使用情况,我在一台 4GB RAM 的机器上运行,(正在使用 1.7)VC9 版本在完成任务之前获得了约 810MB 的内存,而 VC10 则在约 658MB 时崩溃。
这是VC10中的错误吗?我在同一台机器上运行,当完成的工作量相同时,还有什么可能导致内存在一个版本中持续耗尽,而不是在另一个版本中?
<edit>
更多信息:第一次发生异常是在计算堆栈深度为 1 的 7,718,688 时(没有递归只是 main->length)。之后,添加到缓存中的每个数字似乎都会发生这种情况。在异常发生之前,缓存中有 16,777,217 个元素(根据cache.size()
)。有趣的是,即使insert
失败,缓存大小也会增加 1,因此它似乎不提供强异常保证(违反 §23.2.1.11)。
</编辑>
代码如下:
#include <iostream>
#include <unordered_map>
typedef std::unordered_map<_int64, int> cache_type;
_int64 collatz(_int64 i)
{
return (i&1)? i*3+1 : i/2;
}
int length(_int64 n, cache_type& cache)
{
if (n == 1)
return 1;
cache_type::iterator found = cache.find(n);
if (found != cache.end())
return found->second;
int len = length(collatz(n), cache) + 1;
cache.insert(std::make_pair(n, len)); // this sometimes throws
return len;
}
int main(int argc, char** argv)
{
const int limit = 10000000;
cache_type cache;
std::pair<int, int> max = std::make_pair(0, 0);
for (int i = 2; i <= limit; ++i) {
int len = length(i, cache);
if (len > max.second)
max = std::make_pair(i, len);
}
std::cout<< "Number with longest orbit is " << max.first
<< " with a lenght of " << max.second
<< " cache size is " << cache.size() << std::endl;
}
<edit>
任何人都可以重现这种行为,有一次它消失了(然后又重新出现了),所以我的配置可能有一些特别之处。
</编辑>