読者です 読者をやめる 読者になる 読者になる

GCCにバグ報告:最適化オプションを付けるとBoost.Spiritのプログラムが吹っ飛ぶ

GCC C++

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に付属しているMinGWGCC 4.8を使っていて、この問題でしばらく悩んでいました。Windows環境でBoost.SpiritとQtを使う場合、しばらくコンパイラはVisual C++を使うのがいいですね。ちなみにClangではこの問題は発生しません。

Boost.Spiritを使わない再現コードが書けなかったので、仕方なくこれらのコードをそのままGCCに報告しました。

追記

解決しました。