У меня есть следующий код, который вычисляет число Стирлинга второго рода для данного п и к,Почему этот memoized код segfault?
#include <cstdint>
#include <map>
#include <boost/multiprecision/cpp_int.hpp>
namespace mp = boost::multiprecision;
mp::cpp_int stirlingS2(unsigned n, unsigned k)
{
if (n == 0 && k == 0) {
return 1;
}
if (n == 0 || k == 0) {
return 0;
}
static auto memo = std::map<std::pair<unsigned, unsigned>, mp::cpp_int>();
auto nKPair = std::pair<unsigned, unsigned>(n, k);
if (memo.count(nKPair) > 0) {
return memo[nKPair];
}
auto val = k * stirlingS2(n - 1, k) + stirlingS2(n - 1, k - 1);
memo[nKPair] = val;
return val;
}
К сожалению, когда этот код работает, он возвращает ошибку сегментации. Кажется, что он отлично работает для первых значений 87795, вставленных в memo
, но затем сбой вскоре после этого. В частности, segfault происходит в map::count
, в строке if (memo.count(nKPair) > 0) {
. Я подумал, может быть это было делом memo
иссякают размера, поэтому я добавил следующее предостережение в присвоении memo
,
if (memo.size() < memo.max_size()) {
memo[nKPair] = val;
}
Но это не помогло. Я также заметил, что значение 87795 не указывает на то, когда это произойдет. С некоторыми незначительными изменениями, изменяя первый, если заявление,
if (n <= k) {
return 1;
}
изменяет это значение 66453.
Кто-нибудь знает, что здесь происходит?
Где вы планируете вставить что-нибудь в памятку? –
Вы уверены, что segfault находится на 'memo.count' линии и не делать с выдуванием стека через глубокую рекурсию из-за неправильной memoizing? – oldrinb
@DavidThomas, не 'operator []' вставить новый элемент для ключа, если ключ еще не существует? –