1

I have 2 structs that are closely related to each other so i want one struct to reference to the other. Like so:

//inside maze.h
typedef struct{
    char * maze;
    int height, length, cols, rows;
} maze_t;

//inside walker.h
typedef struct {
    int row, col, end_row, end_col, dir, origin;
    maze_t * maze;
} walker_t;

But here is my problem: When i want to print the string walker->maze->maze i get a segmentation fault. It's a lot of code, but i dont know where i made the mistake. The segmentation fault occurs in the move_walker function.

My code:

maze.c:

#include "maze.h"
#include "string.h"
#include "stdio.h"
#include "stdlib.h"

/* Incomplete definitions of the maze support function . */
void init_maze(maze_t* maze, FILE * pFile) {

    int result;

    // obtain file size:
    fseek(pFile , 0 , SEEK_END);
    int lSize, stringPtr;
    lSize= ftell(pFile);
    rewind (pFile);

    // allocate memory to contain the whole file:
    char* string = malloc (sizeof(lSize);
    if (string == NULL) {fputs ("Memory error",stderr); exit (2);}

    // copy the file into the buffer:
    result = fread (string,1,lSize,pFile);
    if (result != lSize) {fputs ("Reading error",stderr); exit (3);}

    fclose(pFile);

    maze->maze = malloc (strlen(string) + 1);

    stringPtr = find_letter_in_string('\n', string);
    strcpy(maze->maze, &string[stringPtr+1]);

    maze->rows = atoi(string);

    stringPtr = find_letter_in_string(',', string);
    maze->cols = atoi(&string[stringPtr+1]);

    printf("Maze has %d rows and %d columns \n", maze->rows, maze->cols);

    return;
}

walker.h:

#include "maze.h"
#include "walker.h"
#include "stdlib.h"
#include "stdio.h"


walker_t* init_walker(maze_t * maze) {

    walker_t* walker = malloc(sizeof(walker_t));

    walker->dir = 0;

    printf("Made room for walker.\n");

    walker->maze = maze;
    locate(maze, 'S',&walker->row, &walker->col);

    printf("Start coordinates: %d, %d.\n", walker->row, walker->col);

    locate(maze, 'E',&walker->end_row, &walker->end_col);

    return walker;
}

int move_walker(walker_t * walker, int row, int col) {

    printf("maze: %s", walker->maze->maze);

    printf("check: %d\n", check_move(walker->maze, row, col));
    if(! check_move(walker->maze, row, col)){
    printf("hello world");
        return 0;
    }
    walker->row = row;
    walker->col = col;
    return 1;
}

main.c:

maze = malloc( sizeof (maze_t));

FILE * pFile = fopen(argv[1],"r");
if(pFile == NULL){
    printf("No such file!\n");
    return 0;
}

init_maze(maze, pFile);
printf("Scrambled the maze.\n");


walker = init_walker(maze);
printf("Woken the walker.\n");

Sorry for spelling mistakes and such, i have dyslexia next to the fact that this is not my native language.

Funonly
  • 818
  • 1
  • 8
  • 22

1 Answers1

1

At least this part is wrong:

result = fread (string,1,lSize,pFile);
// …
maze->maze = (char*)malloc (strlen(string) + 1);

fread does not NUL-terminate string, so you can't use strlen on it reliably, because it looks for the terminating '\0' and thus continues scanning outside your allocated buffer. result would actually contain the number of bytes read in this this case, and you could terminate the string using string[result] = '\0', or simply read with fgets instead. The strlen itself is unnecessary, since you already know the number of bytes read.

In either case you also need to allocate one more byte for the NUL in string:

char* string = malloc(lSize + 1);

The multiplication by sizeof(char) (always 1) and the cast to char * can also be removed for better style, as shown.

Arkku
  • 41,011
  • 10
  • 62
  • 84