undefined behaviour somewhere in boost::spirit::qi::phrase_parse

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_);

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

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.

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;
}

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_);

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:

  • Assigning parsers to auto variables
  • boost spirit V2 qi bug associated with optimization level

¹ 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.