flex yacc(bison)在构建解析树时分段错误

时间:2012-04-11 18:28:14

标签: segmentation-fault bison yacc lex sigsegv

我在逻辑运算符中遇到问题

在我的.y档案中,我有:

expr: expr oper1 expr { $$=insert_expression($2, $1, $3); }
     | expr oper2 expr { $$=insert_expression($2, $1, $3); }
     ;

在我的.l文件中,我确定oper1和oper2是:

"<" | ">" | "=" | "<>" | "<=" | ">=" { return oper1; }
"AND" | "OR" { return oper2; }

然后我有一个结构来将值放在:

typedef struct _Expression
{
    char *oper;
    struct _Expression *ex1;
    struct _Expression *ex2;
} is_expression;

并将值放入:

is_expression* insert_expression(char* oper, is_expression *expr1, is_expression *expr2)
{
    is_expression* e = (is_expression*)malloc(sizeof(is_expression));

    e->ex1 = expr1;
    e->ex2 = expr2;
    e->oper = oper;

    return e;
}

最后告诉他们:

void show_expression(is_expression *e)
{
    show_expression(e->ex1);
    printf("%s", e->oper);
    show_expression(e->ex2);
}

但每次我使用expr oper expr时都会出现分段错误:

Program received signal SIGSEGV, Segmentation Fault

关于我做错了什么的想法?

由于

3 个答案:

答案 0 :(得分:1)

让我们看看:

void show_expression(is_expression *e)
{
    show_expression(e->ex1);
    printf("%s", e->oper);
    show_expression(e->ex2);
}

递归必须有终止的方法!

一个很大的线索是你只有一个printf来打印操作员。但除了运算符之外,树中还有其他内容:即操作数!

在表达式树中,这些操作数是叶节点。他们是如何代表的?他们可能有ex1ex2的空指针,对吧? (希望不是垃圾:你的所有解析器规则都会$$为某个值,对吗?)

此外,您的yacc文件必须有更多。您显示的expr规则本身不存在,因为它不能简化为一系列终端符号。

答案 1 :(得分:0)

所有令牌的默认类型为int。如果你没有

%union {
    char *oper1
    char *oper2
}

会有问题。实际上,你是混合指针和整数。这会导致您的程序尝试访问任意内存,从而导致段错误。

修改

好的,然后在gdb或我首选的cgdb中解开那个东西。

cgdb yourCompiledParser
> r (add necessary command line switches)
when it segfaults
> backtrace

这将为您提供失败的大致位置,并显示您需要断点的位置。有关gdb / cgdb调试提示,请查看此article

答案 2 :(得分:0)

为了获得$n的合理值,您需要%union指令来指定所有可能的类型,然后您需要在%token / {{1中使用这些类型指令:

%type

然后您还需要确保在.l文件中正确设置值:

%union {
    is_expression  *exp;
    char           *str;
}

%token<str> oper1 oper2
%type<exp> expr

否则,您将把随机垃圾作为第一个操作数传递给"<" | ">" | "=" | "<>" | "<=" | ">=" { yylval.str = strdup(yytext); return oper1; } "AND" | "OR" { yylval.str = strdup(yytext); return oper2; } ,然后当您尝试对insert_expression执行任何操作时崩溃(因为它指向随机垃圾)