2014-11-16 31 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個字符。