我的基于野牛的解析器开始窒息我最近生成的一些中等大小的文件。
它引发了关于"内存耗尽的异常。"
野牛手册页说这可能是由于使用了右手递归。不试图重写语法(我在一个紧迫的截止日期),我想简单地增加堆栈以使解析器解析此文件。我试图跟随野牛手册页和#define YYMAXDEPTH到一些大于默认值10000的数字,但那不起作用。当我查看bison的输出时,似乎YYMAXDEPTH仅在定义YYSTACK_RELOCATE时有条件地使用,并且仅在这种情况下定义了YYSTACK_RELOCATE:
#if (! defined yyoverflow \
&& (! defined __cplusplus \
|| (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
&& defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
由于我使用C ++编译,上面的#ifdef失败,因此没有定义YYSTACK_RELOCATE。
这是一个错误还是一个功能?谁知道增加堆栈大小的正确方法是什么?
BTW,这是堆栈溢出的野牛生成代码的片段:
....
....
if (yyss + yystacksize - 1 <= yyssp)
{
/* Get the current used size of the three stacks, in elements. */
YYSIZE_T yysize = yyssp - yyss + 1;
#ifdef yyoverflow
{
/* Give user a chance to reallocate the stack. Use copies of
these so that the &'s don't force the real ones into
memory. */
YYSTYPE *yyvs1 = yyvs;
yytype_int16 *yyss1 = yyss;
YYLTYPE *yyls1 = yyls;
/* Each stack pointer address is followed by the size of the
data in use in that stack, in bytes. This used to be a
conditional around just the two extra args, but that might
be undefined if yyoverflow is a macro. */
yyoverflow (YY_("memory exhausted"),
&yyss1, yysize * sizeof (*yyssp),
&yyvs1, yysize * sizeof (*yyvsp),
&yyls1, yysize * sizeof (*yylsp),
&yystacksize);
yyls = yyls1;
yyss = yyss1;
yyvs = yyvs1;
}
#else /* no yyoverflow */
# ifndef YYSTACK_RELOCATE
goto yyexhaustedlab; // <====== Overflows and throws exception here
# else
......
......
答案 0 :(得分:5)
通常,C ++对象(与C数据类型不同)无法由memcpy
重定位。因此,bison拒绝重新定位其堆栈,除非它以某种方式知道堆栈对象是“微不足道的”,并且如果对象是C ++对象,则假定它们不是。
YYMAXDEPTH
是解析器将分配的最大堆栈,但初始堆栈大小为YYINITDEPTH
。由于无法重新定位C ++堆栈,因此初始大小必须足够大以适应任何输入,因此您需要增加YYINITDEPTH
,而不是YYMAXDEPTH
。
或者,您可以弄清楚如何告诉Bison C ++堆栈对象是可重定位的(如果它们是),或者您可以尝试更新版本的bison:据称,v3更愿意让您自己燃烧,但是我自己没试过。最后,您可以定义yyoverflow
以提供自己的堆栈重定位机制:遗憾的是,这是未记录的,并且不必要地复杂。