0

When I am executing printf command for level->description, the program gives me segmentation fault. I don't know why. Should I use malloc to repair it? The content (only 1 line ending with '\n') of file sokoban.dat is "chicago;addie;story begins here;-----#####-----------|-----#@$.#-----------|-----#####-----------"

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct {
char *name;
char *description;
char *password;
char *map;
struct level *next;
//char *solution;
} LEVEL;

LEVEL* parse_level(char *line) {   //parsing from file into the structure
    LEVEL level;
    char level_name[50];
    char level_password[50];
    char level_description[100];
    char level_map[200];

    int i = 0;
    int j = 0;
    while (line[i] != ';') {      //getting level name
        level_name[j] = line[i];
        i++;
        j++;
    }
    level_name[j]='\0';
    level.name=&level_name[0];
    //strcpy(&level.name,level_name);
    //printf("%s\n",level.name);
    printf("%s\n",level_name);
    j = 0;
    i++;
    while (line[i] != ';') {     //getting level password
        level_password[j] = line[i];
        i++;
        j++;
    }
    level_password[j]='\0';
    level.password=&level_password[0];
    printf("%s\n",level_password);
    j = 0;
    i++;
    while (line[i] != ';') {     //getting level description
        level_description[j] = line[i];
        i++;
        j++;
    }
    level_description[j]='\0';
    level.description=&level_description[0];
    printf("%s\n",level_description);
    j = 0;
    i++;
    while (line[i] != '\n') {    //getting level map
        level_map[j] = line[i];
        i++;
        j++;
    }
    level_map[j]='\0';          
    level.map=&level_map[0];
    printf("%s\n",level_map);
    j = 0;
    level.next=NULL;    
    LEVEL* levelPointer=&level;
    return levelPointer;
}  
int main(){
    FILE *fp = fopen("sokoban.dat", "r");
    if( fp == NULL ){
        printf("No such file\n");
        return 1;
    }

    char line[500];
    //strcpy(line,"");
    char c;
    int i=0;
    while((c = fgetc(fp)) != '\n'){ //reading from file 1 by 1 character
       line[i]=c;
       i++;
    }
    printf("%s\n",line);
    LEVEL* level;
    level=parse_level(line);
    //printf("%s\n",level->description);   **//!!! this is where error occur**
    printf("%s\n",level->map);

    return 0;
}
PeterSW
  • 4,921
  • 1
  • 24
  • 35
Dounchan
  • 319
  • 3
  • 10
  • 1
    Use a debugger such as gdb to find exactly where in your code your problem is, or comment-out portions of your program to narrow down the fault. As it stands, other StackOverflow users are unlikely to work very hard to solve your problem. – Russell Borogove May 09 '14 at 22:53
  • problematic is the 5th row from the bottom (this is when error occurs). I am using NetBeans for debugging and for variable level->description it gives me adress: 0x52
    .
    – Dounchan May 09 '14 at 23:10
  • OK, so is there a mull terminator in there? – Martin James May 09 '14 at 23:22
  • (1)`printf("%s\n",line);` : `line` not null-teminated., – BLUEPIXY May 09 '14 at 23:36
  • (2) `while((c = fgetc(fp)) != '\n'){`...`while (line[i] != '\n') { ` `line` not icluded `\n`. – BLUEPIXY May 09 '14 at 23:37
  • (3) `return levelPointer;` return local value address. – BLUEPIXY May 09 '14 at 23:37
  • Ouh... I think you hit it...'\0' character is not copied from file to `line` variable. – Dounchan May 10 '14 at 00:43
  • but changing `'\0'` to `EOF` does not prevent seg fault. So problem is with returning local variable adress? – Dounchan May 10 '14 at 00:48

2 Answers2

1

In the function, parse_level() you take addresses of all the local variables and copy into the struct variable level and return level. All these copy of local addresses and using those objects later after their lifetime make your program illegal and causes undefined behaviour.

You should read about basics of language first and understand concepts such as pointers, arrays, returning values from a function, returning pointers etc before diving deeper.

The ones related to your problems are:

returning a local variable from function in C

Since I can't return a local variable, what's the best way to return a string from a C or C++ function?

Undefined, unspecified and implementation-defined behavior

Undefined behavior and sequence points

The Definitive C Book Guide and List

Community
  • 1
  • 1
P.P
  • 117,907
  • 20
  • 175
  • 238
  • No doubt that I should study more. The best method is learning by examples. I will get through the links provided by you Anyway, Kernighan & Ritchie book is quite hard to absorb! – Dounchan May 10 '14 at 23:33
0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct level {
    char *name;
    char *description;
    char *password;
    char *map;
    struct level *next;
    //char *solution;
} LEVEL;

#if 0
char *strdup(const char *str){
    size_t len = strlen(str);
    char *ret = malloc(len + 1);
    if(ret){
        memcpy(ret, str, len + 1);
        //ret[len] = '\0';
    }
    return ret;
}
#endif

LEVEL* parse_level(char *line) {
    //Returns the allocated memory
    LEVEL *level = malloc(sizeof(LEVEL));
    char *token;
    token=strtok(line, ";");//It cut the string as a separator the ';'.
    level->name = strdup(token);//Copy the memory allocated strings cut out.

    token=strtok(NULL, ";");//Get next token
    level->password = strdup(token);
    token=strtok(NULL, ";");
    level->description = strdup(token);
    token=strtok(NULL, ";");
    level->map = strdup(token);
    level->next = NULL;
#if DEBUG
    printf("debug print : level\n");
    printf("%s\n", level->name);
    printf("%s\n", level->password);
    printf("%s\n", level->description);
    printf("%s\n", level->map);
#endif
    return level;
}
void LEVEL_free(LEVEL *p){
    free(p->name);
    free(p->password);
    free(p->description);
    free(p->map);
    free(p);
}

int main(){
    FILE *fp = fopen("sokoban.dat", "r");
    if( fp == NULL ){
        printf("No such file\n");
        return 1;
    }

    char line[500];
    char c;
    int i=0;
    while((c = fgetc(fp)) != '\n'){ //reading from file 1 by 1 character
       line[i]=c;
       i++;
    }
    line[i] = '\0';
    printf("%s\n",line);
    LEVEL* level;
    level=parse_level(line);
    printf("%s\n",level->description);
    printf("%s\n",level->map);

    LEVEL_free(level);//free for malloced memory
    return 0;
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70
  • Thank You very much!.....I can now move on. I didn't know of function `strtok()` Actually is this necessary? `#if 0 char *strdup(const char *str){ size_t len = strlen(str); char *ret = malloc(len + 1); if(ret){ memcpy(ret, str, len + 1); //ret[len] = '\0'; } return ret; } #endif` – Dounchan May 10 '14 at 23:21
  • @Dounchan ; I had wrote exemplary `strdup` that isn't a standard function. It isn't required if already exists in the your environment (in ). – BLUEPIXY May 11 '14 at 07:53