boost::spirit::qi::phrase_parse 中某处的未定义行为 [英] undefined behaviour somewhere in boost::spirit::qi::phrase_parse

查看:22
本文介绍了boost::spirit::qi::phrase_parse 中某处的未定义行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习使用 boost::spirit 库.我拿了这个例子 http://www.boost.org/doc/libs/1_56_0/libs/spirit/example/qi/num_list1.cpp 并在我的电脑上编译它 - 它工作正常.

I am learning to use boost::spirit library. I took this example http://www.boost.org/doc/libs/1_56_0/libs/spirit/example/qi/num_list1.cpp and compiled it on my computer - it works fine.

但是,如果我稍微修改它 - 如果我初始化解析器本身

However if I modify it a little - if I initialize the parser itself

auto parser = qi::double_ >> *(',' >> qi::double_);

某处作为全局变量并将其传递给phrase_parse,一切都会变得疯狂.这是完整的修改代码(仅修改了 1 行并添加了 1 行) - http://pastebin.com/5rWS3pMt

somewhere as global variable and pass it to phrase_parse, everything goes crazy. Here is the complete modified code (only 1 line is modified and 1 added) - http://pastebin.com/5rWS3pMt

如果我运行原始代码并将3.14, 3.15"传递给标准输入,它会说解析成功,但我的修改版本失败了.我尝试了许多相同类型的修改 - 将解析器分配给全局变量 - 在某些编译器的某些变体中它会出现段错误.

If I run the original code and pass "3.14, 3.15" to stdin, it says Parsing succeeded, but with my modified version it fails. I tried a lot of modifications of the same type - assigning the parser to global variable - in some variants on some compilers it segfaults.

我不明白为什么会这样以及为什么会这样.这是另一个更简单的版本,它打印 true,然后在 clang++ 上打印段错误,在 g++ 上打印段错误

I don't understand why and how it is so. Here is another, simpler version which prints true and then segfaults on clang++ and just segfaults on g++

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

#include <iostream>
#include <string>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

const auto doubles_parser_global = qi::double_ >> *(',' >> qi::double_);

int main() {
    const auto doubles_parser_local = qi::double_ >> *(',' >> qi::double_);

    const std::string nums {"3.14, 3.15, 3.1415926"};

    std::cout << std::boolalpha;

    std::cout
        << qi::phrase_parse(
            nums.cbegin(), nums.cend(), doubles_parser_local, ascii::space
        )
        << std::endl;                             // works fine

    std::cout
        << qi::phrase_parse(
            nums.cbegin(), nums.cend(), doubles_parser_global, ascii::space
        )                                         // this segfaults
        << std::endl;
}

推荐答案

您不能使用 auto存储解析器表达式¹

You cannot use auto to store parser expressions¹

要么直接从临时表达式求值,要么赋值给规则/语法:

Either you need to evaluate from the temporary expression directly, or you need to assign to a rule/grammar:

const qi::rule<std::string::const_iterator, qi::space_type> doubles_parser_local = qi::double_ >> *(',' >> qi::double_);

在最新的 BOost 版本(可能是 dev 分支)上,你可以吃蛋糕也可以吃,应该有一个 BOOST_SPIRIT_AUTO 宏

You can have your cake and eat it too on most recent BOost versions (possibly the dev branch) there should be a BOOST_SPIRIT_AUTO macro

这已成为常见问题解答:

This is becoming a bit of a FAQ item:

¹ 我相信这实际上是底层 Proto 库的一个限制.github 上有一个 Proto-0x lib 版本(由 Eric Niebler 编写),它承诺通过完全重新设计以了解引用来解决这些问题.我认为这需要一些 Boost Proto 当前无法使用的 c++11 特性.

¹ I believe this is actually a limitation of the underlying Proto library. There's a Proto-0x lib version on github (by Eric Niebler) that promises to solve these issues by being completely redesigned to be aware of references. I think this required some c++11 features that Boost Proto currently cannot use.

这篇关于boost::spirit::qi::phrase_parse 中某处的未定义行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆