Пока пишу пост о проекте 14-й проблемы Эйлера Я столкнулся с разницей в поведении между VC9 и VC10.
Следующий код работает нормально в VC9, нов VC10 std::unordered_map
выдает bad_alloc
исключение.Странно то, что если я восстановлюсь после исключения, будущие выделения будут выполнены успешно (размер контейнера продолжает расти).Также, если я использую boost::unordered_map
, он отлично работает в обоих компиляторах.
Что касается фактического использования памяти, я работаю на машине с 4 ГБ ОЗУ (используется 1,7), версия VC9 получает до ~ 810 МБпамяти до завершения задачи, и VC10 один падает примерно на 658 МБ.
Это ошибка в VC10?Я работаю на той же машине, что еще может привести к постоянному исчерпанию памяти в одной версии, а не в другой, когда объем выполненной работы идентичен?
Дополнительная информация: Первое исключение происходит при вычислении 7 718 688 с глубиной стека 1 (без рекурсии, только main-> length).После этого, похоже, это происходит для каждого числа, которое добавляется в кеш.Кэш содержал 16 777 217 элементов до возникновения исключения (согласно cache.size()
).Интересно то, что даже когда insert
терпит неудачу, размер кэша увеличивается на единицу, поэтому кажется, что он не обеспечивает строгой гарантии исключения (в нарушение §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;
}
Также любой может воспроизвести это поведение, когда-то оно исчезло (и вновь появилось)поэтому в моей конфигурации может быть что-то особенное.