While writing a post about project euler's 14th problem I ran into a difference in behaviour between VC9 and VC10.
The following code runs OK in VC9 but in VC10 std::unordered_map
throws a bad_alloc
exception.
The strange thing is that if I recover from the exception future allocations will succeed (the size of the container continues to grow). Also if I use boost::unordered_map
it works fine in both compilers.
Regarding the actual memory usage, I'm running on a machine with 4GB RAM, (1.7 in use) the VC9 version gets up to ~810MB of memory before completing the task and the VC10 one crashes at ~658MB.
Is this a bug in VC10? I'm running on the same machine what else could cause memory to consistently run out in one version and not in the other when the amount of work done is identical?
<edit>
Some more information: The first time the exception takes place is when calculating 7,718,688 with a stack depth of 1 (no recursion just main->length). After that it seems to happen for each number that is added to the cache. The cache had 16,777,217 elements in it before the exception happened (according to cache.size()
). The interesting thing is that even when insert
fails the cache size grows by one so it appears that it doesn't supply the strong exception guarantee (in violation of §23.2.1.11).
</edit>
Code follows:
#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>
Also can anyone reproduce this behaviour, at one time it disappeared (and re-appeared) so there may be something special about my configuration.
</edit>