2014-11-16 30 views
-1

我正在尝试做作业分配。该任务是生成中间代码。为此,我正在运行以下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 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(); 
} 

和相应的法文件是这样的:

%{ 
#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;} 
%% 

我曾尝试调试程序,但它只是让我无处。我甚至不怎么开始调试它。我确实尝试了printf陈述,但我发现他们没有太多帮助。

我唯一知道的就是它正在检测标识符。编辑:
我试过在这个程序中使用valgrind。这是说,在strcpy源和目的地指向相同的地址。这怎么可能?

+1

尝试调试器。 'gdb'是你的朋友。使用'-g3 -O0'编译并链接所有内容。 –

回答

1

ID你的词法规则返回一个指针到临时标记缓冲液(yytext),其将被覆盖/改变/通过向yylex下一呼叫损坏以读取下一个令牌。试试:

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

改为。

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

更详细地说,您可以拨打code并将&$$作为第一个参数。 $$在调用code之前未设置,所以它可能包含最后一个操作运行后剩下的任何内容,但可能包含任何垃圾,因此这基本上是指向未初始化的回收内存的指针。然后在code中,您可以拨打strcpy(one->lab, ..它从$$.lab中读取随机垃圾指针并尝试复制到它。

您正在将大量内容复制到固定大小的100字节字符缓冲区中,而无需检查溢出。溢出缓冲区将导致腐败。

+0

你是什么意思我正在使用'strcpy()'而不初始化指针到任何地方?它怎么会腐败?我将char缓冲区的大小减少到了30,但它仍然给我分段错误。 –

+0

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

0

在不同的地方使用:

char datatype[5]; 

然后复制到它像这样:

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

的strcpy将复制串加上一个额外的 “空”。一个零来表示字符串的结尾。当你复制“float”时,最后的null将覆盖接下来的任何内容。您需要保留至少6个字符。