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

Bison: $$ and $1 point to the same memory location (union YYSTYPE of two pointer types)

本文关键字:两个 类型 YYSTYPE 指针 位置 1指 内存 Bison      更新时间:2023-10-16

我正在为一个非常简单的解析器构建一个解析器,突然开始获取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); }
%%

这是我的测试.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"上,输出为"gethere!0x372a28|0x372a28"(第二行为"Success!"(,这意味着$1和$$指向相同的内存位置!这当然会导致各种不好的事情发生。

lexer中对yylval.a的赋值是bug显现所必需的。

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

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

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

以及的规则

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

(并删除lexer中的赋值(描述的结果内存位置不同,这让我相信,如果不使用指针,变量本身的内存位置也不同。然而,如果我使用指针,那么赋值"yylval.a=new double((;"应该只更改$1,并保持$$不变。

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

因为你在这里做类型强制(?(,我想你在行动中应该有类似的东西

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

请注意,一旦您写入$$,就无法再读取$1,因为您现在已经占用了$1曾经所在的堆栈插槽。

表达式只有一个组件,因此它的左侧和右侧完全相同。我不知道你为什么会觉得这很奇怪。

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

expression : IDENTIFIER

这意味着expression的一个有效形式是IDENTIFIER。因此,任何是有效IDENTIFIER的东西也是有效expression