0
votes

I've got this segmentation fault on my code. It seems that it appears right after the first variable declaration. Any ideas how can I get rid of this error? Here is a part of my code.

lex file:

%{
#include <stdio.h>
#include "comp-func.h"
#include "y.tab.h"
struct var *create_var(char *s);
%}

%%

"int" {yylval.array = strdup(yytext); return INT;}
0|-?[1-9][0-9]* {yylval.number = atoi(yytext); return INT_NO;}
"main()" {yylval.array = strdup(yytext); return BGIN;}
[_a-zA-Z][_a-zA-Z0-9]* {struct var *vr;
            vr = create_var(yytext);
            yylval.variable = vr; 
            return ID;}
[ \t] ;
\n {yylineno++;}
. {return yytext[0];}

%%

struct var *create_var(char *s)
{
    struct var *vr;
    vr->var_value = 9999;
    vr->var_name = strdup(s);
    vr->next = NULL;
    return vr;
}

yacc file:

%{
#include <stdio.h>
#include <string.h>
#include "comp-func.h"
extern FILE* yyin;
extern char* yytext;
extern int yylineno;
void add_var(struct var *vari);
void print_var(char *var);
int lookup_var(char *var);
%}

%union {
    int number;
    char *array;
    struct var *variable;
}

%token <array> INT 
%token <number> INT_NO 
%token <variable> ID 
%token <array> BGIN
%start progr

%left '-' '+'
%left '*' '/'

%type <number> expr

%%

progr: declaratii bloc {printf("ok\n");}
     ;

declaratii : declaratie_variabila ';'
       | declaratii declaratie_variabila ';'
       ;

declaratie_variabila : INT ID {if(lookup_var($2->var_name)==0)
                                    add_var($2);
                               else 
                               {
                                    printf("Variable -- %s -- is already defined\n",$2->var_name);
                                    return 0;
                               }
                              } 
                 ; 

/* bloc */
bloc : BGIN '{' list '}'  
     ;

/* lista instructiuni */
list : statement ';'
     | list statement ';' 
     ;

/* instructiune */
statement : declaratie_variabila
      | ID '=' expr {if(lookup_var($1->var_name)==0)
             {  
                printf("Variable -- %s -- is not defined\n",$1->var_name);
                return 0;
             }
             else $1->var_value = $3;
            }
          ;

expr : INT_NO
     | expr '+' expr        { $$ = $1 + $3; }
     | expr '-' expr        { $$ = $1 - $3; }
     | expr '*' expr       { $$ = $1 * $3; }
     | expr '/' expr        { $$ = $1 / $3; }
     | '(' expr ')'        { $$ = $2; }
     ;

%%

void add_var(struct var *vari)
{
    struct var *vr;

    vr->next = var_list;

    strcpy(vr->var_name,vari->var_name);

    vr->var_value = vari->var_value;    

    var_list = vr;
}

int yyerror(char * s){
printf("eroare: %s la linia:%d\n",s,yylineno);
}

int main(int argc, char** argv){
yyin=fopen(argv[1],"r");
yyparse();
} 
1
Probably vr ir not allocated (it is only pointer, but You are using it) in yacc file. Anyway - debuger (gdb, ddd or similar) should help.kestasx

1 Answers

1
votes

In create_var:

struct var *create_var(char *s)
{
    struct var *vr;
    vr->var_value = 9999;

vr is not initialized, and then you immediately attempt to use it as though it pointed at allocated memory. That's undefined behaviour (using an uninitialized variable) and segmentation faults are highly likely.

You probably meant something like:

struct var *vr = malloc(sizeof *vr);

Also:

  • don't forget to check to make sure malloc didn't return NULL

  • don't forget to free the allocated memory when you are done with it.