在lex / yacc程序中用_strdup释放分配(用于union)的内存的位置?

时间:2015-02-26 14:32:30

标签: c bison yacc flex-lexer lex

我在yacc / bison文件中定义了以下联合结构:

%union
{
    int num;
    double dbl;
    char ch;
    char *str;
}

在我的lex / flex文件中,我有以下匹配:

[a-zA-Z][a-zA-Z0-9"_"]* { yylval->str = _strdup(yytext); return id; }

我的问题是,我在哪里放置代码以释放“str”?

free(yylval->str);

假设这没关系。请注意,如果我在字符串重复之前放置“free”,则会出现访问冲突:

[a-zA-Z][a-zA-Z0-9"_"]* {
    free(yylval->str);
    yylval->str = _strdup(yytext);
    return id; }

2 个答案:

答案 0 :(得分:1)

你确定需要释放它吗?您在bison文件中的语义操作中对字符串做了什么?如果你只是存储指针,那么就没有任何东西可以释放(还)。如果您再制作一份,请立即将其释放。

答案 1 :(得分:0)

好的,我在yacc / bison文件中使用“str”(char *)做了两件事: 1.我使用strdup制作另一个副本(稍后我将副本释放) 2.我没有使用“char *”(字符串)显式做任何事情,例如,在lex / flex文件中:

";" { return semicolon; }
"foo"|"FOO" { return foo; }
"bar"|"BAR" { return bar; }

...并在yacc / bison文件中:

%token<str> cmd foo bar
...

line:
   cmd prm semicolon { func($2); }
   ;

prm:
    foo { $<num>$ = FOO_ID; }
    |
    bar { $<num>$ = BAR_ID; }
    ;

你是否认为我应该只在第一种情况下释放原始的字符串?

在我的程序的其余部分,我总是在调用_strdup之前调用free(在目标上),清除之前存储的任何内容,这样可以正常工作并且不会导致访问冲突。如果没有释放“yylval-&gt; str”内存会发生什么,当yylval超出范围时它会被释放吗?我很困惑。

(更新)我想我通过在yacc / bison文件中添加以下行找到了解决方案:

%destructor { free($$); } <str>

(另一次更新) ...还为相应的令牌添加了自由(假设在“id”的lex文件中使用了strdup),例如。

match:
   id prm semicolon { func($2); free($1); }
   ;