«cc1plus.exe перестал работать» при компиляции кода Boost Spirit

У меня возникла небольшая проблема при попытке скомпилировать код с использованием последней версии MinGW (GCC 4.5.2) под Windows Vista Home Premium 64- немного. Во время компиляции этого файла я получаю сообщение, что «cc1plus.exe перестал работать», и компиляция завершается неудачно без сообщения об ошибке. Я попытался урезать файл до абсолютного минимума, который все еще вызывает проблему:

#include <boost/spirit/include/classic_file_iterator.hpp>
#include <boost/spirit/include/classic_position_iterator.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/qi.hpp>
#include <vector>

#define BOOST_SPIRIT_AUTO(domain_, name, expr)                                  \
    typedef boost::proto::result_of::                                           \
        deep_copy<BOOST_TYPEOF(expr)>::type name##_expr_type;                   \
    BOOST_SPIRIT_ASSERT_MATCH(                                                  \
        boost::spirit::domain_::domain, name##_expr_type);                      \
    BOOST_AUTO(name, boost::proto::deep_copy(expr));                            \

using namespace std;

//This structure is used to determine the situation in which a certain tile sprite is used.
struct TileCase {
    //A vector of bit fields for which adjacent tiles which must be filled.
    vector<unsigned> filled;

    //A vector of bit fields for which adjacent tiles are optionally filled.
    vector<unsigned> optionalFilled;

    TileCase() :    filled(0),
                    optionalFilled(0){}
};

//Adapt the TileCase struct to a Fusion tuple.
BOOST_FUSION_ADAPT_STRUCT (
    TileCase,
    (std::vector<unsigned>, filled)
    (std::vector<unsigned>, optionalFilled)
)

namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
namespace ascii = boost::spirit::ascii;
using phoenix::function;
using ascii::space;
using ascii::char_;
using qi::eol;

//A skipper rule for comments.
BOOST_SPIRIT_AUTO(qi, comment,  ("/*" >> *(char_ - "*/") >> "*/")
                                | ascii::space
                                | ("//" >> *(char_ - eol) >> eol)
                                );

//The Spirit error handler.
struct error_handler_ {
    template<typename, typename, typename>
    struct result { typedef void type; };

    template <typename Iterator>
    void operator()(
        qi::info const& what,
        Iterator err_pos, Iterator last) const
    {
        //Get the line position.
        boost::spirit::classic::file_position_base<string> const& pos = err_pos.get_position();

        //Throw an error.
        stringstream error;
        error << "Error! Expecting "
              << what
              << " at line "
              << pos.line
              << ", column "
              << pos.column
              << "!";
        throw(runtime_error(error.str()));
    }
};

function<error_handler_> const error_handler = error_handler_();

//The Spirit grammar for parsing tile data.
template<typename Iterator>
struct tileData : qi::grammar<Iterator, vector<TileCase>(), comment_expr_type> {
    //The rule called when the parsing starts.
    qi::rule<Iterator, vector<TileCase>(), comment_expr_type> start;

    //The rule for parsing a single tile case.
    qi::rule<Iterator, TileCase(), qi::locals<unsigned>, comment_expr_type> tile;

    //The rule which parses yes/no/either bitflag blocks.
    //Takes two references to unsigned, the first being the yes/no flag and the second being the optional flag.
    qi::rule<Iterator, void(unsigned&, unsigned&), qi::locals<unsigned>, comment_expr_type> condBlock;

    tileData() : tileData::base_type(start) {
        using qi::eps;
        using qi::lit;
        using qi::on_error;
        using qi::fail;
        using qi::uint_;
        using phoenix::at_c;
        using phoenix::push_back;
        using phoenix::resize;
        using namespace qi::labels;

        start = *tile[push_back(_val, _1)];

        tile =
            //Parse the filled definition.
            lit("filled")

        >   '('
            //Parse the generation to check for fills.
        >   uint_
            [
                _a = _1,
                resize(at_c<0>(_val), _1 + 1),
                resize(at_c<1>(_val), _1 + 1)
            ]
        >   ')'
            //Opening curly bracket for filled definition.
        >   '{'
            //The condition block.
        >   condBlock
            (
                //This one goes to filled[_a],
                (at_c<0>(_val))[_a],
                //and optionalFilled[_a].
                (at_c<1>(_val))[_a]
            )
            //Closing curly bracket for filled definition.
        >   '}'
        ;

        condBlock =
            eps
            [_a = 1]
        >>
            (
            *   (
                    (
                        +lit('+')
                        [_r1 += _a, _a *= 2]
                    )
                |
                    (
                        +lit('*')
                        [_r2 += _a, _a *= 2]
                    )
                |
                    (
                        +lit('-')
                        [_a *= 2]
                    )
                )
            )
        ;

        on_error<fail>
        (
            start,
            error_handler(_4, _3, _2)
        );
    }
};


int main() {
    try {
        //Set up the file iterator.
        typedef char char_type;
        typedef boost::spirit::classic::file_iterator<char_type> iterator_type;

        //Open the file.
        iterator_type first("Test.txt");

        //Make sure the file is open.
        if (!first) throw(runtime_error("Failed to open file!"));

        //Find the end of the file.
        iterator_type last = first.make_end();

        //Wrap the file iterator with a position iterator.
        typedef boost::spirit::classic::position_iterator2<iterator_type> pos_iterator_type;
        typedef tileData<pos_iterator_type> tileData;
        pos_iterator_type pos_first(first, last, "Test.txt");
        pos_iterator_type pos_last;

        //Prepare parsing information.
        tileData tileData_parser;
        vector<TileCase> cases;

        //Parse the file.
        if (phrase_parse(pos_first, pos_last, tileData_parser, comment, cases) && pos_first == pos_last) {
            //Do something...
        }
    }
    catch (const exception& e) {
        cerr << "Exception while reading file:\n" << e.what() << endl;
        return 1;
    }

    return 0;
}

В этой урезанной версии компилятор дает сбой только в том случае, если включены символы отладки (-g). Однако с полной версией файла все равно вылетает. Кроме того, если часть кода Spirit удалена (например, обработчик ошибок или средство пропуска комментариев), он также компилируется правильно. Это говорит о том, что компилятору не хватает памяти, но я не совсем уверен, как это исправить.

Я пробовал строить прямо из командной строки, а также из Code :: Blocks, но cc1plus все еще вылетает. Единственный флаг компилятора, который я включил, - это -g. Я дважды проверил, что у меня установлена ​​только одна установка MinGW, и попытался переустановить ее, но проблема не исчезла. Что могло бы вызвать это?

5
задан TheLastBanana 25 July 2011 в 02:17
поделиться