Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1678 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  Bug avec boost::spirit::qi et flag -O2

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Bug avec boost::spirit::qi et flag -O2

n°2222068
Terminapor
I'll see you rise.
Posté le 11-03-2014 à 14:49:51  profilanswer
 

Hi there :hello:

 

J'ai écris un parseur de fichier texte en utilisant boost::spirit::qi qui marche très bien.
Je viens d'essayer de compiler en release (avec le flag -O2) et là, il est incapable de me parser mon fichier :sweat:

 

Voilà la class qui gère les règles :

 

(mp::Property est une structure, mp::Type est un enum, MaterialInfo est la structure renvoyée )

 
Code :
  1. //-------------------------------------------------------
  2. // Material parser
  3. // Performs the parsing
  4. template < typename iterator_t, typename skipper_t >
  5. class MaterialParser : public qi::grammar< iterator_t, Graphic::MaterialInfo(), skipper_t >
  6. {
  7.     private:
  8.         //----------------------------------------------------
  9.         // Rules
  10.         qi::rule< iterator_t, std::string() > GenericStringRule;
  11.         qi::rule< iterator_t, mp::Property(), skipper_t > PropertyRule;
  12.         qi::rule< iterator_t, std::vector<mp::Property>(), skipper_t > PropertiesGroupRule; 
  13.         qi::rule< iterator_t, Graphic::MaterialInfo(), skipper_t > MaterialRule;
  14.         //-----------------------------------------------------
  15.         //-----------------------------------------------------
  16.         // Symbols
  17.         qi::symbols< char, mp::Type > PropertyTypeSymbols;
  18.         //-----------------------------------------------------
  19.     public:
  20.         MaterialParser() : MaterialParser::base_type( MaterialRule )
  21.         {
  22.             //-----------------------------------
  23.             // Set-up symbols ( properties types )
  24.             PropertyTypeSymbols.add
  25.                   ("int", mp::TYPE_int)
  26.                  ("uint", mp::TYPE_uint)
  27.                 ("float", mp::TYPE_float)
  28.                 ("ivec2", mp::TYPE_ivec2)
  29.                 ("ivec3", mp::TYPE_ivec3)
  30.                 ("ivec4", mp::TYPE_ivec4)
  31.                 ("uvec2", mp::TYPE_uvec2)
  32.                 ("uvec3", mp::TYPE_uvec3)
  33.                 ("uvec4", mp::TYPE_uvec4)
  34.                  ("vec2", mp::TYPE_vec2)
  35.                  ("vec3", mp::TYPE_vec3)
  36.                  ("vec4", mp::TYPE_vec4);
  37.             //-----------------------------------
  38.             //-----------------------------------
  39.             // Generic string rule
  40.             // a-z, A-Z, 0-9, _
  41.             GenericStringRule = +(ascii::char_("a-zA-Z0-9_" ));
  42.             GenericStringRule.name("string" );
  43.             //-----------------------------------
  44.             //-----------------------------------
  45.             // Property rule
  46.             // {type} {name};
  47.             PropertyRule = (PropertyTypeSymbols) > (GenericStringRule) > (qi::lit(";" ));
  48.             //-----------------------------------
  49.             //-----------------------------------
  50.             // Group rule
  51.             // name { [...] }
  52.             PropertiesGroupRule = (qi::lit("properties" )) > (qi::lit("{" )) > (*PropertyRule) > (qi::lit("}" ));
  53.             //-----------------------------------
  54.             MaterialRule = +( (PropertiesGroupRule[ phx::bind( &Graphic::MaterialInfo::SetProperties, qi::_val, qi::_1 ) ]) );
  55.         }
  56. };
  57. //-------------------------------------------------------
 

Pour ce qui est de l'invocation, ça se passe comme ça :

 
Code :
  1. Graphic::MaterialInfo ParseMaterial( std::istream& Input, const std::string& RefFileName )
  2. {
  3.     //-------------------------------------------------------------------------
  4.     // Aliases declaration
  5.     using base_iterator_type = std::istreambuf_iterator<char> ;
  6.     using forward_iterator_type = boost::spirit::multi_pass<base_iterator_type>;
  7.     using pos_iterator_type = classic::position_iterator2<forward_iterator_type>;
  8.     //-------------------------------------------------------------------------
  9.     //-------------------------------------------------------------------------
  10.     // Generate all iterators, initialize them
  11.     base_iterator_type InputIt ( Input );
  12.     forward_iterator_type fwd_first = boost::spirit::make_default_multi_pass( InputIt );
  13.     forward_iterator_type fwd_last;
  14.     pos_iterator_type pos_first(fwd_first, fwd_last, RefFileName );
  15.     pos_iterator_type pos_last;
  16.     //-------------------------------------------------------------------------
  17.     Graphic::MaterialInfo Result;
  18.     MaterialParser<pos_iterator_type, ascii::space_type > Parser;
  19.     try
  20.     {
  21.         //-------------------------
  22.         // Perform the actual parse
  23.         bool r = qi::phrase_parse(
  24.                 pos_first, pos_last,
  25.                 Parser,
  26.                 ascii::space,
  27.                 Result
  28.         );
  29.         //-------------------------
  30.         //-------------------------------
  31.         // Check for completeness
  32.         if (!r || pos_first != pos_last)
  33.         {
  34.             std::stringstream Message;
  35.             const classic::file_position_base<std::string>& Pos = pos_first.get_position();
  36.             Message<<"Line # "<<Pos.line <<" at position "<< Pos.column<<std::endl;
  37.             Message<<pos_first.get_currentline()<<std::endl;
  38.             for ( int i=1;i<Pos.column;++i) Message<<' ';
  39.             Message<<"^ here"<<std::endl;
  40.             throw std::runtime_error( Message.str() );
  41.         }
  42.         //-------------------------------
  43.     }
  44.     // Pas le catch ici, l'erreur est reportée dans la condition if !r || pos_first != post_last )
  45.     return Result;
  46. }
 

Toutes les structures parsées par les règles sont adaptés à boost::spirit::qi avec BOOST_FUSION_ADAPT_STRUCT (certaine le sont partiellement ceci-dit, j'ai des attributs de ces structures qui ne sont pas utilisés par le parseur, ça peut être gênant ? :??:)

 

Mon fichier d'entrée :

 
Code :
  1. properties {
  2.         int i;
  3.         uint u;
  4.         float f;
  5. }
 

Et le parser se stop dès le première caractère, il m'affiche ça :

 


Line # 1 at position 1
properties {
^ here

 

Je sais pas tellement ce qui se passe, on dirait que le compilateur optimise les opérateurs utilisés pour générer les règles, mais j'ai pas trouvé grand chose sur internet :/

 

Merci à vous :jap:

 

edit : J'ai oublié de préciser, les namespace boost sont ré-associés pour raccourcir un peu (dans le cpp) :

 
Code :
  1. namespace qi = boost::spirit::qi;
  2. namespace ascii = boost::spirit::ascii;
  3. namespace classic = boost::spirit::classic;
  4. namespace phx = boost::phoenix;


Message édité par Terminapor le 11-03-2014 à 14:51:29

---------------
Perhaps you don't deserve to breathe
mood
Publicité
Posté le 11-03-2014 à 14:49:51  profilanswer
 

n°2222077
Terminapor
I'll see you rise.
Posté le 11-03-2014 à 16:27:33  profilanswer
 

Je up vite fait, j'ai trouvé la source du problème.

 

Ca vient de classic::position_iterator2 apparemment :

 
Code :
  1. using base_iterator_type = std::istreambuf_iterator<char> ;
  2. using forward_iterator_type = boost::spirit::multi_pass<base_iterator_type>;
  3. using pos_iterator_type = classic::position_iterator<forward_iterator_type>;
  4. base_iterator_type Input_ ( Input );
  5. forward_iterator_type fwd_first = boost::spirit::make_default_multi_pass( Input_ );
  6. forward_iterator_type fwd_last;
  7. pos_iterator_type pos_first(fwd_first, fwd_last, fName );
  8. pos_iterator_type pos_last;
 

Si j'utilise pos_first / pos_last dans boost::qi::phrase_parse, ça marche sans optimisation, mais -O2 ruine tout (testé sur un exemple tout simple de parsing de nombres "1, 2, 3, etc" ).
Si j'utilise fwd_first / fwd_last, là les deux sont bons.

 

J'utilise Boost 1.54, je vais tenter de recompiler cet exemple avec -O2 sur la version 1.55 et je mettrai à jour ce post. :jap:

 

edit : Recompilé avec Boost 1.55, aucun soucis en debug/release :jap:


Message édité par Terminapor le 11-03-2014 à 16:52:23

---------------
Perhaps you don't deserve to breathe

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  Bug avec boost::spirit::qi et flag -O2

 

Sujets relatifs
type de retour de la fonction binomial_coefficient de boostInstallation de boost sous visual C++ 2010
Bug programme asm 8086Bug module paybox
Programme répertoire téléphonique (BUG) HELP PLEASE !!![PHP] php_flag ne marche pas
Bug sur retour jour semaineProgrammation d'un jeu : BUG !
boost::shared_ptr et std::auto_ptrqueue avec variables conditionnelles (boost)
Plus de sujets relatifs à : Bug avec boost::spirit::qi et flag -O2


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR