Yacc/Lex给出了此代码的分段错误

Yacc/Lex给出了此代码的分段错误,c,yacc,lex,C,Yacc,Lex,我正在做家庭作业。任务是生成中间代码。为此,我正在运行下面的Yacc程序,以及Lex。然而,它给了我一个分割错误。为什么会出现分段错误?这是代码 %{ #include<stdio.h> #include<malloc.h> #include<string.h> #include<ctype.h> char datatype[5]; char temporaryVariable[5]; int assignment=0; int tempvarn

我正在做家庭作业。任务是生成中间代码。为此,我正在运行下面的Yacc程序,以及Lex。然而,它给了我一个分割错误。为什么会出现分段错误?这是代码

%{
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<ctype.h>

char datatype[5];
char temporaryVariable[5];
int assignment=0;
int tempvarnum=0;

struct sym
{
    char datatype[5];
    char varname[5];
    int size,location;
    struct sym *next;
}*first;

struct quadruple
{
    char *src1;
    char *src2;
    char *op;
    char *tmp;
    struct quadruple *next;
}*qfirst;

char* typeOf(char *lab);


void yyerror(const char *st)
{}
%}

%left '+' '-'
%left '*' '/'
%right '^'
%union 
{
    struct ICG
    {
        char *lab; 
        char code[100]; 
        char datatype[5];
    }Icg;
}
%token <Icg> ID
%token INT FLOAT CHAR
%type <Icg> E

%%
S: S Decl
 | Decl 
 | S Assn
 | Assn
 ;

Decl:Type List ';' {printf("Read declaration list");}
    ;

List:List ',' ID {printf("created node\n");createNode($3.lab,datatype);}
    | ID {printf("created node\n");createNode($1.lab,datatype);}
    ;

Type: INT {strcpy(datatype,"int");}
    | FLOAT {strcpy(datatype,"float");}
    | CHAR {strcpy(datatype,"char");}
    ;

Assn:ID '=' E ';' {printf("Assignment statement");assignment=0;}
    ;


E: E '+' E {printf("Entering code");code(&$$,&$1,&$3,'+');}
 | E '-' E {code(&$$,&$1,&$3,'-');}
 | E '*' E {code(&$$,&$1,&$3,'*');}
 | E '/' E {code(&$$,&$1,&$3,'/');}
 | ID {printf("ID");strcpy($$.code,$1.lab); strcpy($$.lab,$1.lab);strcpy($$.datatype,typeOf($1.lab));}
 ;
%%

void code(struct ICG* one, struct ICG* two, struct ICG* three, char *operator)
{
    printf("In code");
    char tempvarname[5];
    char code[100];
    sprintf(tempvarname,"t%d=",tempvarnum++);
    strcpy(one->lab,tempvarname);
    strcpy(one->lab,two->lab);
    createNode(one->lab,one->datatype);
    strcpy(code,tempvarname);
    strcat(code,two->lab);
    strcat(code,three->lab);
    strcat(code,operator);
    strcat(code,"\n");

    if(assignment==0)
    {
        strcpy(one->code,code);
        assignment=1;
    }
    else
    {
        strcat(one->code,code);
    }
    createQuadruples(two->lab,three->lab,operator,one->lab);
}

void createQuadruples(char *lab2,char*lab3,char *operator,char*lab1)
{
    struct quadruple* next=qfirst;
    if(!next)
    {
        struct quadruple* new=(struct quadruple*)malloc(sizeof(struct quadruple));
        strcpy(new->src1,lab2);
        strcpy(new->src2,lab3);
        strcpy(new->op,operator);
        strcpy(new->tmp,lab1);
        new->next=NULL;
        qfirst=new;
    }
    else
    {
        while(next->next)
        {
            next=next->next;
        }
        struct quadruple* new=(struct quadruple*)malloc(sizeof(struct quadruple));
        strcpy(new->src1,lab2);
        strcpy(new->src2,lab3);
        strcpy(new->op,operator);
        strcpy(new->tmp,lab1);
        new->next=NULL;
        next->next=new;
    }
}

void displayCode()
{
    struct quadruple* temp=qfirst;
    int i=0;
    printf("\t| %s | Label | size | location |\n","Index");
    while(temp)
    {
        printf("\t|%7d|%7s|%6s|%7s|%8s|\n",i++,temp->src1,temp->op,temp->src2,temp->tmp);
        temp=temp->next;
    }   
}

char* typeOf(char *lab)
{
    struct sym *new=first;
    while(new)
    {
        if(strcmp(new->varname,lab)==0)
        {
            return new->datatype;
        }
        new=new->next;
    }
}




void createNode(char *name, char *type)
{
    struct sym* new=first;
    int size=0;
    if(strcmp(type,"char")==0)
        size=1;
    if(strcmp(type,"float")==0)
        size=4;
    if(strcmp(type,"int")==0)
        size=2;

    if(!new)
    {
        struct sym* next=(struct sym*)malloc(sizeof(struct sym));
        strcpy(next->datatype,type);
        strcpy(next->varname,name);
        next->size=size;
        next->location=0;
        next->next=NULL;
        first=next;
    }
    else
    {
        while(new->next)
        {
            new=new->next;
        }
        struct sym* next=(struct sym*)malloc(sizeof(struct sym));
        strcpy(next->datatype,type);
        strcpy(next->varname,name);
        next->size=size;
        next->location=new->location+new->size;
        next->next=NULL;
        new->next=next;
    }
}
int main()
{
    yyparse();
    printf("In main");
    displayCode();
}
%{
#包括
#包括
#包括
#包括
char数据类型[5];
字符时间变量[5];
int赋值=0;
int tempvarnum=0;
结构符号
{
char数据类型[5];
charvarname[5];
int大小、位置;
结构符号*下一步;
}*第一,;
四联结构
{
char*src1;
char*src2;
char*op;
char*tmp;
结构四倍*下一步;
}*qfirst;
字符*类型(字符*实验室);
无效错误(常量字符*st)
{}
%}
%左'+''-'
%左'*''/'
%对‘^’
%联合
{
结构ICG
{
char*实验室;
字符码[100];
char数据类型[5];
}全球导航卫星系统国际委员会;
}
%令牌ID
%标记整型浮点字符
%E型
%%
S:S十二月
|十二月
|S助理
|助理
;
Decl:类型列表“;”{printf(“读取声明列表”);}
;
List:List','ID{printf(“创建的节点”);createNode($3.lab,datatype);}
|ID{printf(“已创建节点\n”);createNode($1.lab,datatype);}
;
类型:INT{strcpy(数据类型,“INT”);}
|FLOAT{strcpy(数据类型,“FLOAT”);}
|CHAR{strcpy(数据类型,“CHAR”);}
;
助理:ID'='E';'{printf(“赋值语句”);赋值=0;}
;
E:E'+'E{printf(“输入代码”);代码(&$$,&$1,&$3,'+');}
|E'-'E{code(&$$,&$1,&$3,'-');}
|E'*'E{code(&$$,&$1,&$3,'*');}
|E'/'E{code(&$$,&$1,&$3,'/');}
|ID{printf(“ID”);strcpy($$.code,$1.lab);strcpy($$.lab,$1.lab);strcpy($$.datatype,typeOf($1.lab));}
;
%%
无效代码(结构ICG*1、结构ICG*2、结构ICG*3、字符*运算符)
{
printf(“代码中”);
char tempvarname[5];
字符码[100];
sprintf(tempvarname,“t%d=,tempvarnum++);
strcpy(一个->实验室,tempvarname);
strcpy(一个->实验室,两个->实验室);
createNode(一个->实验室,一个->数据类型);
strcpy(代码,tempvarname);
strcat(代码,二->实验室);
strcat(代码,三->实验室);
strcat(代码、操作员);
strcat(代码“\n”);
如果(赋值==0)
{
strcpy(一->代码,代码);
赋值=1;
}
其他的
{
strcat(一->代码,代码);
}
创建四个(两个->实验室,三个->实验室,操作员,一个->实验室);
}
void createquartples(char*lab2、char*lab3、char*operator、char*lab1)
{
结构四联*next=qfirst;
如果(!下一个)
{
struct fourple*new=(struct fourple*)malloc(sizeof(struct fourple));
strcpy(新->src1,lab2);
strcpy(新->src2,lab3);
strcpy(新建->操作,操作员);
strcpy(新->tmp,lab1);
新建->下一步=空;
qfirst=新的;
}
其他的
{
while(下一步->下一步)
{
下一步=下一步->下一步;
}
struct fourple*new=(struct fourple*)malloc(sizeof(struct fourple));
strcpy(新->src1,lab2);
strcpy(新->src2,lab3);
strcpy(新建->操作,操作员);
strcpy(新->tmp,lab1);
新建->下一步=空;
下一步->下一步=新建;
}
}
void displayCode()
{
结构四倍*temp=qfirst;
int i=0;
printf(“\t |%s |标签|大小|位置| \n”,“索引”);
while(临时)
{
printf(“\t |%7d |%7s |%6s |%7s |%8s | \n”,i++,temp->src1,temp->op,temp->src2,temp->tmp);
温度=温度->下一步;
}   
}
字符*类型(字符*实验室)
{
结构符号*新=第一个;
while(新)
{
如果(strcmp(新->变量名,实验室)==0)
{
返回新建->数据类型;
}
新建=新建->下一步;
}
}
void createNode(字符*名称,字符*类型)
{
结构符号*新=第一个;
int size=0;
if(strcmp(类型,“字符”)==0)
尺寸=1;
如果(strcmp(类型,“浮动”)==0)
尺寸=4;
如果(strcmp(类型,“int”)==0)
尺寸=2;
如果(!新建)
{
struct sym*next=(struct sym*)malloc(sizeof(struct sym));
strcpy(下一步->数据类型,类型);
strcpy(next->varname,name);
下一步->大小=大小;
下一步->位置=0;
下一步->下一步=空;
第一个=下一个;
}
其他的
{
while(新建->下一步)
{
新建=新建->下一步;
}
struct sym*next=(struct sym*)malloc(sizeof(struct sym));
strcpy(下一步->数据类型,类型);
strcpy(next->varname,name);
下一步->大小=大小;
下一步->位置=新建->位置+新建->尺寸;
下一步->下一步=空;
新建->下一步=下一步;
}
}
int main()
{
yyparse();
printf(“主要”);
显示代码();
}
相应的lex文件如下:

%{
#include<stdio.h>
#include "y.tab.h"
%}

letter [a-zA-Z]
digit [0-9]

%%
"int" {return INT;}
"float" {return FLOAT;}
"char" {return CHAR;}
"+"|"-"|"*"|"/"|"="|","|";" {return yytext[0];}
{letter}({letter}|{digit})* {yylval.Icg.lab=yytext;return ID;}
%%
%{
#包括
#包括“y.tab.h”
%}
字母[a-zA-Z]
数字[0-9]
%%
“int”{return int;}
“float”{返回float;}
“char”{return char;}
“+”|“-“|”*“|”/“|”=“|”、“|”;”{返回yytext[0];}
{letter}({letter}{digit})*{yylval.Icg.lab=yytext;返回ID;}
%%
我确实试着调试这个程序,但它只是让我一事无成。我甚至不知道如何开始调试它。我确实尝试了
printf
语句,但我发现它们没有多大帮助

我唯一能确定的是,它正在检测标识符

编辑:

我试着在这个程序中使用valgrind。也就是说,在strcpy中,源和目标指向相同的地址。这是怎么可能的?

您的
ID
lexer规则将指针返回到临时令牌缓冲区(
yytext
),下次调用
yylex
读取下一个令牌时,该缓冲区将被覆盖/更改/损坏。尝试:

{letter}({letter}|{digit})* {yylval.Icg.lab=strdup(yytext);return ID;}
相反

code
函数(以及其他地方)中,您正在使用
strcpy
将指针复制到
one->lab
指向的内存中,而从未初始化指向任何位置的指针。即时内存损坏

更详细地说,您可以使用
&$$
作为第一个参数调用
code
$
在调用
code
之前未设置,因此它可能包含上次操作运行后留在其中的任何内容,但可能包含任何垃圾,因此这本质上是指向未初始化的可回收内存的指针。然后在<
char datatype[5];
Type: INT {strcpy(datatype,"int");}
    | FLOAT {strcpy(datatype,"float");}
    | CHAR {strcpy(datatype,"char");}