【发布时间】:2016-08-08 21:57:09
【问题描述】:
我有以下代码计算给定 n 和 k 的第二类斯特林数,
#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;
}
不幸的是,当这段代码运行时,它会出现段错误。插入memo 的前 87795 个值似乎运行良好,但此后不久就崩溃了。具体来说,段错误发生在map::count,在if (memo.count(nKPair) > 0) { 行中。我想这可能是memo 的大小不足的问题,所以我在memo 的分配中添加了以下警告,
if (memo.size() < memo.max_size()) {
memo[nKPair] = val;
}
但这并没有帮助。我还注意到 87795 值并不表示何时崩溃。通过一些小的修改,将第一个 if 语句更改为,
if (n <= k) {
return 1;
}
将该值更改为 66453。
有人知道这里发生了什么吗?
【问题讨论】:
-
你打算在哪里插入一些东西到备忘录中?
-
你确定段错误在
memo.count行上,而不是由于没有正确记忆而导致通过深度递归炸毁堆栈? -
@DavidThomas,如果键不存在,
operator[]不会为键插入新元素吗? -
@JordyDickinson 是的,确实如此......但是地图中的所有内容都是默认构造的 cpp_int。这是故意的吗?
-
你为什么用
if (memo.count(nKPair) > 0) { return memo[nKPair]; }而不是auto it = memo.find(nKPair); if (it != memo.end()) return it.second;?你在哪里插入地图?
标签: c++ boost segmentation-fault memoization boost-multiprecision