编译Boost Spirit代码时“cc1plus.exe已停止工作”

时间:2011-07-25 02:17:36

标签: mingw 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,我尝试重新安装它,但问题仍然存在。会导致这种情况发生的原因是什么?

2 个答案:

答案 0 :(得分:3)

这是gcc / MingW的一个已知问题,但我不知道它的状态是什么(它是否已被重新编辑等等)Spirit邮件列表上的某个人提出了一个增加默认堆栈大小的补丁。据报道cc1plus.exe修复了这个问题。不过,我没有尝试过自己。

答案 1 :(得分:0)

看起来pch文件有一个硬限制值,大约是128M,请参阅我最近编辑过的答案:https://stackoverflow.com/a/19372020/154911 我在mingw-w64论坛上询问他们是否可以构建一个新的工具链来解决这个问题。