Bug 59709 - break program behavior with optimization
GCC 4.8.1、GCC 4.8.2で最適化オプション(たとえば-O2)を付けると、Boost.Spiritを使ったコードが吹っ飛びます。
吹っ飛びますというのは、プログラムの次の行が実行されず、どこかに行ってしまう、ということです。セグメンテーションフォルトで落ちることもあれば、if文で実行される節がelseの方に行ってしまったり(正しくはthenの方)もします。環境によって挙動が変わります。
再現コードは以下:
#include <iostream> #include <string> #include <boost/spirit/include/qi.hpp> namespace qi = boost::spirit::qi; int main() { const std::string input = "hello:"; auto rule = *(qi::char_ - ':') >> ':'; std::string::const_iterator it = input.begin(); std::string result; if (qi::parse(it, input.end(), rule, result)) { std::cout << "parse successful" << std::endl; } else { std::cout << "parse failed" << std::endl; } }
最適化を付けないで実行すると、このプログラムは「parse successful」を出力します。これが正しい挙動です。
これを-O2で実行すると、MacPorts GCC 4.8.1環境では何も出力されませんでした(if文がthenでもelseでもないどこかに行った)。WandboxのGCC 4.8.1、GCC 4.8.2ではelse節が実行され「parse failed」が出力されます。
ルールの型としてautoを使わず、qi::ruleを使えばこの問題は発生しません。
#include <iostream> #include <string> #include <boost/spirit/include/qi.hpp> namespace qi = boost::spirit::qi; int main() { const std::string input = "hello:"; qi::rule<std::string::const_iterator, std::string()> rule = *(qi::char_ - ':') >> ':'; std::string::const_iterator it = input.begin(); std::string result; if (qi::parse(it, input.end(), rule, result)) { std::cout << "parse successful" << std::endl; } else { std::cout << "parse failed" << std::endl; } }
このプログラムは、最適化オプションを付けても付けなくても、「parse successful」が出力されます。
Windows向けのQt 5.2に付属しているMinGWのGCC 4.8を使っていて、この問題でしばらく悩んでいました。Windows環境でBoost.SpiritとQtを使う場合、しばらくコンパイラはVisual C++を使うのがいいですね。ちなみにClangではこの問題は発生しません。
Boost.Spiritを使わない再現コードが書けなかったので、仕方なくこれらのコードをそのままGCCに報告しました。
追記
解決しました。