如何增加野牛的堆栈大小(并解决"memory exhausted")



我的基于bison的解析器开始被我最近生成的一些中等大小的文件阻塞。

它抛出了一个关于"内存耗尽"的异常

野牛手册页说,这可能是由于使用了右手递归。在不试图重写语法的情况下(我的最后期限很紧),我只想增加堆栈,让解析器解析这个文件。我试图遵循野牛手册页,并将#define YYMAXDEPTH定义为大于默认10000的某个数字,但没有成功。当我查看bison的输出时,似乎只有在定义了YYSTACK_RELOCATE时才有条件地使用YYMAXDEPTH,并且只有在这种情况下才定义了YY斯塔克_RELOCATE:

#if (! defined yyoverflow 
&& (! defined __cplusplus 
|| (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL 
&& defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))

由于我是用C++编译的,所以上面的#ifdef失败了,因此没有定义YYSTACK_RELOCATE。

这是bug还是功能?有人知道增加堆栈大小的正确方法是什么吗?

顺便说一句,这是野牛生成的代码片段,堆栈溢出:

....
....
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
......
......

通常,与C数据类型不同的C++对象不能由memcpy重新定位。因此,bison拒绝重新定位其堆栈,除非它不知何故知道堆栈对象是"琐碎的",并且如果对象是C++对象,它会假设它们不是。

YYMAXDEPTH是解析器将分配的最大堆栈,但初始堆栈大小为YYINITDEPTH。由于C++堆栈无法重新定位,因此初始大小必须足够大,以用于任何输入,因此需要增加YYINITDEPTH,而不是YYMAXDEPTH

或者,你可以想办法告诉bison C++堆栈对象是可重定位的(如果是的话),或者你可以尝试更新版本的bison:据称,v3更愿意让你自焚,但我自己还没有尝试过。最后,您可以定义yyoverflow来提供自己的堆栈重新定位机制:不幸的是,这是未记录的,而且不必要地复杂。

相关内容

最新更新