我尝试使用最新版本的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,我尝试重新安装它,但问题仍然存在。会导致这种情况发生的原因是什么?
答案 0 :(得分:3)
这是gcc / MingW的一个已知问题,但我不知道它的状态是什么(它是否已被重新编辑等等)Spirit邮件列表上的某个人提出了一个增加默认堆栈大小的补丁。据报道cc1plus.exe修复了这个问题。不过,我没有尝试过自己。
答案 1 :(得分:0)
看起来pch文件有一个硬限制值,大约是128M,请参阅我最近编辑过的答案:https://stackoverflow.com/a/19372020/154911 我在mingw-w64论坛上询问他们是否可以构建一个新的工具链来解决这个问题。