2016-12-30 1 views
3

次のコードを実行するとクラッシュします。どうして? boost :: spirit :: multi_passが述語と代替語でクラッシュする

#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を間違って使用しているような気がしますが、問題は正確にはわかりません。

+2

信頼性をもって2倍を解析しようとしていますか? https://stackoverflow.com/search?q=strict_real_policies – sehe

+0

を検索してください。いいえ、これは私が可能な限りシンプルにするための例です。それにもかかわらず、これは他の場所で役に立つでしょう。ありがとう! –

+0

これは未定義ビヘイビアの性質です。結果が定義されていないため、推論できません。 – sehe

答えて

2

単に終了イテレータの初期化子を修正。

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); 
} 
+0

これはコードをはっきりと修正しますが、クラッシュを引き起こすためにはなぜ述語と代替コンビネーションが必要なのかは依然として謎です。実際の使用例では、文字列イテレータを 'multi_pass'にラップしていません。それにもかかわらず、私は 'multi_pass'の使用が間違っていると私の疑惑を確認しています。 –

2

マルチパスのイテレータでstd :: stringをラップすることはできません。少なくともiterator_policies::buffering_input_iteratorではなく、std :: stringにはendのヌルではないポインタがあります。そのため、イテレータは互換性がなくなります。 std::stringを構文解析する場合は、iteratorを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; 
}