为什么使用yyclearin不会在野牛中触发%destructor

时间:2018-02-07 20:28:20

标签: bison flex-lexer

虽然有一个%析构函数处理程序,但在bison语法的错误恢复中出现内存泄漏。这似乎取决于yyclearin的使用。

以下是语法摘录:

%union {
    int val;
    const char* str; /* allocated in the lexer with strdup() */
}
%token <int> KEYWORD
%token <str> STR
%destructor { free($$); } <str>
...
%%
...
problem
    : KEYWORD KEYWORD STR {doSomething(); free($3); }
    | KEYWORD ERROR       { yyclearin; yyerrok; someResync(); }
    ;

对于以下输入:

KEYWORD KEYWORD "string1"
KEYWORD "string2"

第一个输入行与第一个规则匹配,字符串被手动释放&#39;通过归属行动。 第二个输入行被错误规则选中。该字符串作为前瞻读取 令牌触发错误并被yyclearin遗忘。但是 分配的内存仍然泄漏。需要做些什么来调用%析构函数?

1 个答案:

答案 0 :(得分:1)

这是一个很好的问题。

我原本以为丢弃前瞻标记会属于&#34;当用户操作无法管理内存时#34;。但所有yyclearin都会重置yych,强制在下次需要预测时读取新令牌。

实际上,这意味着您的使用操作(调用yyclearin)需要管理内存。通过稍微闯入野牛的内部,我们可以相当简单地做到这一点:

#define my_yyclearin \
      yydestruct ("Clearin: discarding", yytoken, &yylval); \
      yychar = YYEMPTY;

(如果您使用地理位置,则必须在yylloc电话中添加yydestruct。)

yydestruct是一个未记录的bison内部函数,它调用正确的析构函数并在启用跟踪时打印出teace消息。 yytokenyychar中保留的令牌值的内部版本(使用压缩范围的索引值来减小表大小)。 yycharyylval变量已记录在案,因此它们应该可以安全使用。

这充其量只是一个原始的解决方法。我已将此问题报告为野牛维护者的错误。