Сетка класса C ++ (std :: vector of ячейки), пользовательская функция изменения размера вызывает ошибку сегментации - PullRequest
0 голосов
/ 30 марта 2020

У меня есть двумерный класс сетки, который состоит из ячеек, я должен хранить ячейки в 1D std::vector (из-за спецификации), который моделирует двумерную сетку.

Я написал Grid::resize функция, которая изменяет размер сетки до новой ширины и высоты, но сохраняет содержимое сетки в пределах сохраняемой области (все новые ячейки установлены на Cell::DEAD).

Я написал функцию изменения размера, которая при запуске вызывает ошибку сегментации: 11, что, как я полагаю, означает, что функция пытается получить доступ к данным за пределами вектора, но я не уверен, где находится ошибка.

Класс

class Grid {
private:
    std::vector<Cell> grid_cells;
    unsigned int width;
    unsigned int height;
public:
    Grid(const unsigned int width, const unsigned int height);
}

Код конструктора

Grid::Grid(const unsigned int width, const unsigned int height) {
    std::vector<Cell> cells(width*height);
    int i;
    for(i=0;i<(width*height);i++){
        cells[i] = Cell::DEAD;
    }
    this->width = width;
    this->height = height;
    this->grid_cells = cells;
}

Функция изменения размера

void Grid::resize(const unsigned int new_width, const unsigned int new_height) {

    std::vector<Cell> new_cells(new_width*new_height);
    unsigned int x, y;

    for(x = 0; x < new_width; x++) {
        for(y = 0; y < new_height; y++) {

            if(x < this->width && y < this->height) {
                new_cells[get_index(x,y)] = this->grid_cells[get_index(x,y)];
            }
            else {
                new_cells[get_index(x,y)] = Cell::DEAD;
            }
        }
    }

    this->width = new_width;
    this->height = new_height;

    this->grid_cells = new_cells;
}

Мой код проверяется с помощью запуска на нем готовых наборов тестов, я полагаю, что ошибка происходит из тела цикла for, потому что когда я комментирую это, тестовый набор запускается до конца, но когда он покидает его, я получаю ошибку сегментации, и он перестает работать.

Редактировать:

get_index функция для преобразования 2D х координата у 1D индекс:

const unsigned int Grid::get_index(const unsigned int x, const unsigned int y) const{
    return ((y * this->width) + x + 1);
}

1 Ответ

1 голос
/ 30 марта 2020
const unsigned int 
Grid::get_index(const unsigned int x, const unsigned int y) const{
    return ((y * this->width) + x + 1);
}

Вы используете исходную ширину сетки для вычисления индекса в новой сетке. Они могут сильно отличаться, поэтому вы скопируете неправильную ячейку или получите доступ к памяти за пределами new_cells

Более того, как и всегда, вы всегда выполняете недопустимые обращения к памяти при попытке получить доступ к последней ячейке с координатой (width-1, height-1), что на height*width - width + width -1 + 1 = height*width. Последний действительный индекс для вектора: height*width-1

Вы можете использовать свободную функцию

unsigned int 
get_index(const unsigned int x, const unsigned int y, const unsigned int width) const{
    return (y * width) + x ;
}

и иметь

new_cells[get_index(x,y, new_width)] = this->grid_cells[get_index(x,y, this->width)]
...