为什么这个memoized代码段错误?

时间:2016-08-08 21:57:09

标签: c++ boost segmentation-fault memoization boost-multiprecision

我有以下代码计算给定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::countif (memo.count(nKPair) > 0) {中。我想也许这是memo超出规模的问题,所以我在memo的作业中添加了以下警告,

if (memo.size() < memo.max_size()) {
    memo[nKPair] = val;
}

但这并没有帮助。我还注意到87795值并不表示何时崩溃。通过一些小修改,将第一个if语句更改为,

if (n <= k) {
    return 1;
}

将该值更改为66453。

有谁知道这里发生了什么?

1 个答案:

答案 0 :(得分:1)

好的,经过几个小时的混乱之后,我将其缩小为表达式模板问题。我并不完全理解为什么,但这一切都与行

中的那个小auto有关
auto val = k * stirlingS2(n - 1, k) + stirlingS2(n - 1, k - 1)

基本上,将auto更改为mp::cpp_int,然后突然,不会出现段错误。