arrayscdynamicdynamic-memory-allocationmaze

Problem with assigning value to reallocated dynamic array - maze solver


I am struggling with storing value to dynamic array, which was reallocated by realloc() function.

I am creating maze solver program and as a inner representation I want to create 1D array tile_array of struct tile elements where every element represents one read character from input file. The struct tile stores character and additional data such as distance in the array, row and col (abstraction) etc. The maze is represented in struct maze which contains the tile array.

I need to dynamically allocate the tile_array since length of input file is not known. In every iteration of while loop the program creates a struct tile and assignes it to the end of the 1D array. It works ok till this point. When the array is full, it calls realloc() and continues storing elements to the end of the array. Here is the problem and I dont see the cause. From this point, the printf() function prints NULL for every parameter.

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

struct tile
{
    // should be one element in tile array
    bool visited;
    char type;              // '#' / ' ' / 'X' / 'o'
    size_t distance;        // distance in tile_array
    size_t row;
    size_t col;
    struct tile* previous;  // pointer to previous tile
};

struct maze
{
    struct tile* tile_array;    // 1D array of <tile> structs
    size_t length;              // length of tile_array
    size_t *rows_lengths;          // [row1_len, row2_len, ...]
    size_t row_count;           // count of rows used
};


bool maze_create(struct maze *maze, FILE *file)
{
    size_t array_length = 4;

    // allocate tile_array
    struct tile *tile_array = malloc(array_length * sizeof(struct tile));
    if (tile_array == NULL) {
        return false;
    }

    // allocate rows_lengths array
    size_t rows_lengths_count = 4;
    size_t *rows_lengths = malloc(rows_lengths_count * sizeof(size_t));
    if (rows_lengths == NULL) {
        free(tile_array);
        tile_array = NULL;
        return false;
    }

    char curr_char;
    size_t curr_distance = 0;
    size_t curr_row = 0;
    size_t curr_col = 0;
    struct tile *previous = NULL;
    while ((curr_char = fgetc(file)) != EOF) {
        assert(curr_distance <= array_length);
        assert(curr_row <= rows_lengths_count);

        // allocate more memory for tile_array
        if (curr_distance == array_length) {
            array_length += 4;
            struct tile *tmp = realloc(tile_array, (array_length * sizeof(struct tile)));
            if (tmp == NULL) {
                free(tile_array);
                tile_array = NULL;
                free(rows_lengths);
                rows_lengths = NULL;
                return false;
            }
            tile_array = tmp;
            tmp = NULL;
        }

        // allocate more memory for rows_lengths
        if (rows_lengths_count == curr_row) {
            rows_lengths_count += 4;
            size_t *tmp = realloc(rows_lengths, (rows_lengths_count * sizeof(size_t)));
            if (tmp == NULL) {
                free(tile_array);
                tile_array = NULL;
                free(rows_lengths);
                rows_lengths = NULL;
                return false;
            }
            rows_lengths = tmp;
            tmp = NULL;
        }

        if (curr_char == '\n') {
        // set variables & continue
        }
        if (illegal_input_char(curr_char)) {
        // invalid input, free memory & return false
        }

        // create new tile and insert to the maze
        struct tile curr_tile = {false, curr_char, curr_distance, curr_row, curr_col, previous};
        tile_array[curr_distance] = curr_tile;

        printf("WRITTEN CHAR: '%lu', direction:%2lu", ((*maze).tile_array[curr_distance]).type, ((*maze).tile_array[curr_distance]).distance);

        curr_col++;
        curr_distance++;
        previous = &curr_tile;
    }

    (*maze).length = curr_distance;
    (*maze).row_count = curr_row - 1;
    return true;
}

Solution

  • From what I see in the code, tile_array and rows_lengths are just local variables, and they are not the same as tile_array and rows_lengths members of the Maze.

    However when you print them out, you refer to members of Maze, hence null output. You probably wanted to refer to (*maze).tile_array and (*maze).rows_lengths everywhere.