【问题标题】:boost::spirit::multi_pass crash with predicate and alternativeboost::spirit::multi_pass 崩溃与谓词和替代
【发布时间】:2017-05-15 04:06:17
【问题描述】:

运行以下代码会导致崩溃。为什么?

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_multi_pass.hpp>

using namespace boost::spirit;
typedef multi_pass<
            std::string::const_iterator,
            iterator_policies::default_policy<
                iterator_policies::first_owner,
                iterator_policies::no_check,
                iterator_policies::buffering_input_iterator,
                iterator_policies::split_std_deque>>
        string_mp_iterator;

int main() {
    std::string input = "234";
    string_mp_iterator input_begin(input.begin()),
            input_end((string_mp_iterator()));
    qi::rule<string_mp_iterator, boost::variant<int, double>()> r =
            &qi::lit('1') >> qi::int_ | qi::double_;
    qi::parse(input_begin, input_end, r);
    return 0;
}

要重现崩溃,我似乎需要同时拥有谓词和后续替代方案,使用multi_pass 迭代器,并且输入不满足谓词。

我感觉我在这里错误地使用了multi_pass,但我看不出问题到底出在哪里。

【问题讨论】:

  • 您是否试图可靠地解析双精度数和整数?搜索stackoverflow.com/search?q=strict_real_policies
  • 不,这只是我试图让事情尽可能简单的一个例子。这在其他地方仍然有用。谢谢!
  • 这就是未定义行为的本质:您无法对其进行推理,因为结果未定义

标签: c++ boost boost-spirit boost-spirit-qi


【解决方案1】:

只需修复结束迭代器的初始化程序。

string_mp_iterator input_end(input.end());

由于它不是输入迭代器,所以不能合法地使用默认构造的迭代器。

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_multi_pass.hpp>

using namespace boost::spirit;
typedef multi_pass<
    std::string::const_iterator,
    iterator_policies::default_policy<
        iterator_policies::first_owner, iterator_policies::no_check,
        iterator_policies::buffering_input_iterator,
        iterator_policies::split_std_deque>>
    string_mp_iterator;

int main() {
    std::string input = "234";
    string_mp_iterator input_begin(input.begin()),
                       input_end(input.end());
    qi::rule<string_mp_iterator, boost::variant<int, double>()> r = &qi::lit('1') >> qi::int_ | qi::double_;
    qi::parse(input_begin, input_end, r);
}

【讨论】:

  • 这清楚地修复了代码,但对我来说仍然是一个谜,为什么谓词和替代组合是导致崩溃的必要条件。在我的真实用例中,我没有将字符串迭代器包装到multi_pass 中。尽管如此,这确实证实了我对multi_pass 的使用不正确的怀疑。
【解决方案2】:

似乎你不能用 multi_pass 迭代器包装 std::string,至少不能用 iterator_policies::buffering_input_iterator 包装 std::string 有一个基于 end 的指针,而不是空值。这就是迭代器出现不兼容的原因。如果您只想解析 std::string,请直接使用迭代器,因为它们满足 multi_pass 的要求。如果你打算改成流(code sorta from here)

typedef std::istreambuf_iterator<char> base_iterator_type;
typedef boost::spirit::multi_pass<base_iterator_type> forward_iterator_type;

main( )
{
    std::istringstream input( "234" );

    base_iterator_type in_begin(input);
    base_iterator_type in_end;
    forward_iterator_type fwd_begin = boost::spirit::make_default_multi_pass(in_begin);
    forward_iterator_type fwd_end   = boost::spirit::make_default_multi_pass(in_end);

    qi::rule<forward_iterator_type, boost::variant<int, double>()> r =
        &qi::lit('1') >> qi::int_ | qi::double_;
    qi::parse(fwd_begin, fwd_end, r);
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多