Bison:$$和$ 1指向相同的内存位置(两个指针类型的联合YYSTYPE)

时间:2011-11-08 00:49:45

标签: c++ c bison flex-lexer

当我突然开始获得SEGFAULT时,我正在构建一个非常简单的解析器的解析器。我已经将我的代码剥离到最小的地方:

这是我的test.flex文件:

%{
#include "test.tab.h"
#include <iostream>
using namespace std;
%}
%option noyywrap
%%
model { yylval.a = new double(); return IDENTIFIER; }
.     { cerr << "Unrecognized token!" << endl; exit(1); }
%%

这是我的test.y文件:

%{
#include <iostream>
using namespace std;
int yylex();
int yyerror(const char *p) { cerr << "Error" << endl; }
%}

%union YYSTYPE {
  double* a;
  int* b;
};

%token <a> IDENTIFIER 
%type <b> expression

%%
expression : IDENTIFIER { cout << "got here! " << $1 << "|" << $$ << endl; };
%%

int main()
{
  yyparse();
  cout << "Success!" << endl;
  return 0;
}

我们的联盟由两个指针a和b组成。 $ 1和$$是不同类型的(分别为a和b)。

在输入“model”上,输出“到达这里!0x372a28 | 0x372a28”(和第二行的“Success!”),这意味着$ 1和$$指向相同的内存位置!这当然会导致各种不好的事情发生。

要显示错误,需要在词法分析器中对yylval.a进行分配。

我使用Bison 2.4.1和Flex 2.5.4,两者都用于Windows(使用GnuWin32)。难道我做错了什么?这是一个(已知的)错误吗?

编辑: 如果我将联合更改为:

%union YYSTYPE {
  int a;
  int b;
};

的规则
expression : IDENTIFIER { cout << "got here! " << &$1 << "|" << &$$ << endl; };

(并删除词法分析器中的赋值)描述的结果内存位置不同,这使我相信如果没有使用指针,变量本身的内存位置会有所不同。但是,如果我使用指针就是这种情况,则赋值为“yylval.a = new double();”应该只改变$ 1并保持$$不受影响。

2 个答案:

答案 0 :(得分:1)

这不是Bison中的一个错误,这就是Bison的工作方式。它使用一个堆栈来处理中间解析结果,并且在你的规则中有一个令牌要从堆栈中移出而另一个要添加,因此要弹出的项目和要推送的项目显然位于同一个记忆位置。

因为你在这里做类型强制(?),我想你在行动中应该拥有的是

double *a = $1;
$$ = new int((int)(*a));
delete a;

请注意,一旦你写入$$,就不能再读取1美元,因为你现在已经占用了曾经是1美元的堆栈槽。

答案 1 :(得分:0)

表达式只有一个组件,因此它的左侧和右侧完全相同。我不确定你为什么觉得这很令人惊讶。

我想我可能知道你的困惑在哪里:

expression : IDENTIFIER

这表示expression的一个有效表单是IDENTIFIER。因此,任何有效的IDENTIFIER也是有效的expression