0
#include <iostream>
#include <fstream>
#include <string>

struct TextGrid {
    char         **tiles;
    unsigned int   height;
    unsigned int   width;
};

void paint(TextGrid& grid, unsigned int x, unsigned int y, char fill) {
    if (x < grid.width && y < grid.height) {
        grid.tiles[y][x] = fill;
    }
}
void resize(TextGrid& grid, unsigned int width, unsigned int height, char fill) {
    char **newTiles = new char*[height];
    for (unsigned int i = 0; i < height; ++i) {
        newTiles[i] = new char[width];
        for (unsigned int j = 0; j < width; ++j) {
            if (i < grid.height && j < grid.width) {
                newTiles[i][j] = grid.tiles[i][j];
            }
            else {
                newTiles[i][j] = fill;
            }
        }
    }

    for (unsigned int i = 0; i < grid.height; ++i) {
        delete[] grid.tiles[i];
    }
    delete[] grid.tiles;

    grid.tiles = newTiles;
    grid.width = width;
    grid.height = height;
}

void transform(TextGrid& grid, char target, char replacement) {
    for (unsigned int i = 0; i < grid.height; ++i) {
        for (unsigned int j = 0; j < grid.width; ++j) {
            if (grid.tiles[i][j] == target) {
                grid.tiles[i][j] = replacement;
            }
        }
    }
}

TextGrid load_grid(std::string file_path) {
    std::ifstream infile(file_path);
    std::string line;
    std::getline(infile, line);
    unsigned int height = 1;
    unsigned int width = line.length();
    while (std::getline(infile, line)) {
        ++height;
    }
    infile.clear();
    infile.seekg(0, std::ios::beg);

    TextGrid grid;
    grid.tiles = new char*[height];
    grid.height = height;
    grid.width = width;
    for (unsigned int i = 0; i < height; ++i) {
        grid.tiles[i] = new char[width];
        std::getline(infile, line);
        for (unsigned int j = 0; j < width; ++j) {
             grid.tiles[i][j] = line[j];
        }
    }
    infile.close();
    return grid;
}

void save_grid(TextGrid& grid, std::string file_path) {
    std::ofstream outfile(file_path);
    for (unsigned int i = 0; i < grid.height; ++i) {
        for (unsigned int j = 0; j < grid.width; ++j) {
            outfile << grid.tiles[i][j];
        }
        outfile << '\n';
    }
    outfile.close();
}

void show(TextGrid& grid) {
    for (unsigned int i = 0; i < grid.height; ++i) {
        for (unsigned int j = 0; j < grid.width; ++j) {
            std::cout << grid.tiles[i][j];
        }
        std::cout << '\n';
    }
}

int main() {
    TextGrid grid;
    grid.width = 16;
    grid.height = 8;
    grid.tiles = new char*[grid.height];
    for (unsigned int i = 0; i < grid.height; ++i) {
        grid.tiles[i] = new char[grid.width];
        for (unsigned int j = 0; j < grid.width; ++j) {
            grid.tiles[i][j] = ' '; 
        }
        paint(grid, 5, 2, 'X');
    }
    resize(grid, 20, 10, '.');
    transform(grid, 'X', 'O');
    save_grid(grid, "output.txt");
    TextGrid loaded_grid = load_grid("output.txt");
    show(loaded_grid);

    for (unsigned int i = 0; i < grid.height; ++i) {
        delete[] grid.tiles[i];
    }
    delete[] grid.tiles;

    for (unsigned int i = 0; i < loaded_grid.height; ++i) {
         delete[] loaded_grid.tiles[i];
    }
    delete[] loaded_grid.tiles;

    return 0;
}

I keep getting error message Segmentation fault (core dumped). I tested the program through valgrind and got an error that there was use of an uninitialized value and and Invalid write of size 1 in the paint function. I cant figure out what the problem is. There are no memory leaks that valgrind has detected. the uninitialized value error occurred at line 4023AF in the "paint" function, and it involves a value of size 8. The Invalid write of size 1 also occurred at line 4023AF in the "paint" function. The program attempted to write a value of size 1 to memory at address 0x5.

  • 3
    `struct TextGrid { std::vector> tiles; };` -- Then all the problems go away. – PaulMcKenzie Apr 23 '23 at 22:52
  • [Here is your program](https://godbolt.org/z/PM68oeMss) rewritten using `std::vector`. No check was made as to the running of the program, but all of the calls to `new` and `delete`, plus the handling of raw pointers, has been eliminated. Also, the size of the amount of code written was reduced. – PaulMcKenzie Apr 23 '23 at 23:14
  • @PaulMcKenzie that changed the output of my program is there a way to edit my original code without changing the struct. This is for an assignment and I have to use the struct in my original program. – alexa hrnicek Apr 23 '23 at 23:45
  • In the very first loop in `main`, you call `paint(grid, 5, 2, 'X');` before `grid.tiles[2]` has ben assigned a value. Whereupon your program exhibits undefined behavior. – Igor Tandetnik Apr 24 '23 at 00:24
  • @IgorTandetnik how do i implement that into my program? – alexa hrnicek Apr 24 '23 at 05:32
  • Run your program in a [debugger](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) and check what happens when it crashes - inspect the call stack leading up to the crash, the values of local variables and function arguments in the crashing stack frame and those leading up to the crash, etc, to figure out what's going on - in short; debug the problem. You can also load a core dump into the debugger to see what went wrong. – Jesper Juhl Apr 24 '23 at 07:04
  • You say that memcheck generates an error. If you are using a debug build then the memcheck error should give you the file and line where the error is happening. You will have to work out if your allocations were big enough, your indices correct and whether or not you forgot to initialize memory. – Paul Floyd Apr 24 '23 at 10:08
  • Also concentrate on the invalid and uninitialized memory errors before leaks. Leaks are generally far less serious and won't cause your exe to crash. – Paul Floyd Apr 24 '23 at 10:15
  • How do you implement *what* into your program? I don't quite understand the question. – Igor Tandetnik Apr 24 '23 at 11:50

1 Answers1

0

The issue with your code is in load_grid function. You are remaining extra lines, but they are not used. This results in uninitialized memory being used to store the loaded TextGrid.

i.troyen
  • 69
  • 5