Boost::spirit program crashes

Here my stripped version still crashes with segfault: ----<snio>---- #include <boost/spirit.hpp> #include <iostream> using namespace boost::spirit; struct Configurable { const char* name; // name of the configurable module const rule<>& parser; // parser for config items, normally // a couple of OR-connected terms. }; rule<> __ = ch_p(' '); // separator char. was a bit more complex // in the original code std::string conn, port, ident_name, ident_pw; /* // the original parser crashes with segfault: const Configurable cfg = { "Hardtest", +( *__ | ("connect" >> __ >> str_p[assign_a(conn)] >> ':' >> int_p[assign_a(port)]) | ("identity" >> __ >> str_p[assign_a(ident_name)] >> __ >> str_p[assign_a(ident_pw)] ) | "hard" ) }; */ // a simplicistic parser that still crashes: const Configurable cfg = { "Hardtest", +( __ ) }; int main(int argc, char** argv) { // original config string: // "connect foo.bar:123 identity root fF2.oby!sy" or the like. parse("hard ", cfg.parser); // <--- CRASHES! // this works: // parse("hard ", +(__) ); }; ----<snap>---- The stack trace of GNU gdb is: Program received signal SIGSEGV, Segmentation fault. 0x000000000040184e in boost::spirit::impl::rule_base<boost::spirit::rule<boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t>, boost::spirit::rule<boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t> const&, boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t>::parse_main<boost::spirit::scanner<char const*, boost::spirit::scanner_policies<boost::spirit::iteration_policy, boost::spirit::match_policy, boost::spirit::action_policy> > > (this=0x7fff29fcea10, scan=@0x7fff29fcea00) at /usr/include/boost/spirit/core/non_terminal/impl/rule.ipp:189 189 hit = rule_base_access::get(*derived_this) (gdb) bt #0 0x000000000040184e in boost::spirit::impl::rule_base<boost::spirit::rule<boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t>, boost::spirit::rule<boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t> const&, boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t>::parse_main<boost::spirit::scanner<char const*, boost::spirit::scanner_policies<boost::spirit::iteration_policy, boost::spirit::match_policy, boost::spirit::action_policy> > > (this=0x7fff29fcea10, scan=@0x7fff29fcea00) at /usr/include/boost/spirit/core/non_terminal/impl/rule.ipp:189 #1 0x00000000004018f7 in boost::spirit::impl::rule_base<boost::spirit::rule<boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t>, boost::spirit::rule<boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t> const&, boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t>::parse<boost::spirit::scanner<char const*, boost::spirit::scanner_policies<boost::spirit::iteration_policy, boost::spirit::match_policy, boost::spirit::action_policy> > > (this=0x7fff29fcea10, scan=@0x7fff29fcea00) at /usr/include/boost/spirit/core/non_terminal/impl/rule.ipp:171 #2 0x000000000040197b in boost::spirit::parse<char const*, boost::spirit::rule<boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t> > (first_=@0x7fff29fcea58, last=@0x7fff29fcea68, p=@0x7fff29fcea10) at /usr/include/boost/spirit/core/impl/parser.ipp:28 #3 0x0000000000401a34 in boost::spirit::parse<char, boost::spirit::rule<boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t> > (str=0x402420 "hard ", p=@0x7fff29fcea10) at /usr/include/boost/spirit/core/impl/parser.ipp:45 #4 0x0000000000400973 in main (argc=1, argv=0x7fff29fceb88) at cfgTest.cc:38 I am using boost 1.35 (yes, it is quite old. Is this a bug in boost that is fixed in newer versions? I didn't found something related in the changelogs) on Linux x86_64, gcc 4.3.2 (Debian "Lenny"). Perhaps somebody knows an answer except "use spirit 2!" :-) Lars R.

On 3/26/2010 3:35 PM, Lars Rohwedder wrote:
Here my stripped version still crashes with segfault:
----<snio>---- #include<boost/spirit.hpp> #include<iostream>
using namespace boost::spirit;
struct Configurable { const char* name; // name of the configurable module const rule<>& parser; // parser for config items, normally // a couple of OR-connected terms. };
rule<> __ = ch_p(' '); // separator char. was a bit more complex // in the original code
std::string conn, port, ident_name, ident_pw;
[...]
// a simplicistic parser that still crashes: const Configurable cfg = { "Hardtest", +( __ ) };
int main(int argc, char** argv) { // original config string: // "connect foo.bar:123 identity root fF2.oby!sy" or the like. parse("hard ", cfg.parser); //<--- CRASHES!
// this works: // parse("hard ", +(__) ); }; ----<snap>----
[...]
Perhaps somebody knows an answer except "use spirit 2!" :-)
You have a dangling reference to a rule here: const rule<>& parser; when you do this: const Configurable cfg = { "Hardtest", +( __ ) }; +( __ ) creates a temporary rule and you assign the address of that to cfg.parser. Remove the reference: const rule<> parser; Keep in mind though that "classic" spirit rules are not copyable. So don't go and copy your cfg around. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net http://www.facebook.com/djowel Meet me at BoostCon http://www.boostcon.com/home http://www.facebook.com/boostcon

You have a dangling reference to a rule here:
const rule<>& parser;
when you do this:
const Configurable cfg = { "Hardtest", +( __ ) };
+( __ ) creates a temporary rule and you assign the address of that to cfg.parser.
I thought I bound the temporary to a const reference, so the temporary lives as long as the reference lives, like in this example: std::string& s = std::string("Foo") + "Bar";
Remove the reference:
const rule<> parser;
Keep in mind though that "classic" spirit rules are not copyable. So don't go and copy your cfg around.
That's why I want to use references, to avoid copying rules around. I solved the problem by writing // unchanged: struct Configurable { const char* name; const rule<>& rule; }; // make an explicit object here, not a bound temporary: const rule<> myRule = +(__)>>(...); // bound the reference to the copy: const Configurable cfg = {"Name", myRule }; and it seems to work. :-) Lars R.

On 3/26/2010 9:43 PM, Lars Rohwedder wrote:
I solved the problem by writing
// unchanged: struct Configurable { const char* name; const rule<>& rule; };
// make an explicit object here, not a bound temporary: const rule<> myRule = +(__)>>(...);
// bound the reference to the copy: const Configurable cfg = {"Name", myRule };
and it seems to work. :-)
Yes, that will work. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net http://www.facebook.com/djowel Meet me at BoostCon http://www.boostcon.com/home http://www.facebook.com/boostcon
participants (2)
-
Joel de Guzman
-
Lars Rohwedder