プロジェクト euler の 14 番目の問題に関する投稿を書いているときに、VC9 と VC10 の動作の違いに遭遇しました。
次のコードは、VC9 では正常に実行されますが、VC10 では例外std::unordered_map
がスローされbad_alloc
ます。奇妙なことは、例外から回復すると、将来の割り当てが成功することです (コンテナーのサイズは大きくなり続けます)。また、使用するboost::unordered_map
と、両方のコンパイラで正常に動作します。
実際のメモリ使用量に関しては、4GB RAM (使用中は 1.7) のマシンで実行しています。VC9 バージョンはタスクを完了する前に最大 810MB のメモリを取得し、VC10 バージョンは最大 658MB でクラッシュします。
これは VC10 のバグですか? 私は同じマシンで実行していますが、実行される作業量が同じである場合に、一方のバージョンでは一貫してメモリが不足し、もう一方のバージョンではメモリが不足する原因となるものは他にありますか?
<編集>
いくつかの詳細情報:例外が最初に発生するのは、スタックの深さ 1 で 7,718,688 を計算するときです (メインから長さだけの再帰はありません)。その後、キャッシュに追加される番号ごとに発生するようです。キャッシュには、例外が発生する前に 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;
}
<編集>
また、誰でもこの動作を再現できます。一度は消えた (そして再び現れた) ため、私の構成には何か特別なものがあるかもしれません。
</編集>