xcode — плохо знаком с C ++, & quot; EXC_BAD_ACCESS & quot; ошибка, которую я не понимаю

Я пытаюсь перевести двумерный клеточный автомат из обработки в openFrameworks (C ++). Я написал классы для клеток и для функциональности игры жизни. Приложение успешно собирается, но сразу завершается с ошибкой: Поток 1: Программа получила сигнал: «EXC_BAD_ACCESS».

Вот мой заголовок моей игры класса жизни

#include "Cell.h"
class GoL {

public:
GoL();
void init();
void generate();
void display();
void run();

int w = 20;
int cols;
int rows;

std::vector<vector<cell> > board;};

и вот реализация:

#include "GoL.h"
GoL::GoL() {
cols = ofGetWidth() / w;
rows = ofGetHeight() / w;
board[rows][cols];
init();
}

void GoL::run() {
generate();
display();
}

void GoL::init() {
for (int i = 0; i < cols; i ++) {
for (int j = 0; j < rows; j ++) {
board[i][j] = *new cell(i * w, j * w, w);
}
}
}

void GoL::generate() {
for (int i = 0; i < cols; i ++) {
for (int j = 0; j < rows; j ++) {
board[i][j].savePrevious();
}
}
for (int x = 0; x < cols; x ++) {
for (int y = 0; y < cols; y ++) {
int neighbours = 0;
for (int i = -1; i <= 1; i ++) {
for (int j = -1; j <= 1; j ++) {
neighbours += board[(x + i + cols) % cols][(y + j + rows) % rows].previous;
}
}
neighbours -= board[x][y].previous;
// Rules of Life
if      ((board[x][y].state == 1) && (neighbours <  2)) board[x][y].newState(0);
else if ((board[x][y].state == 1) && (neighbours >  3)) board[x][y].newState(0);
else if ((board[x][y].state == 0) && (neighbours == 3)) board[x][y].newState(1);
}
}
}

void GoL::display() {
for (int i = 0; i < cols; i ++) {
for (int j = 0; j < rows; j ++) {
board[i][j].display();
}
}
}

ошибка отображается в файле vector.h, в заголовочном файле GoL и там, где я вызываю метод init () в реализации GoL. Буду признателен за любую оказанную помощь.

0

Решение

У вас есть доступ вне границ, потому что вектор имеет размер 0:

board[rows][cols];

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

GoL::GoL() : cols(ofGetWidth()/w), rows(ofGetHeight()/w), board(rows, std::vector<cell>(cols))
{
}

Это будет инициализировать board быть размером rowsи каждый из его элементов будет вектором размера cols, Затем вы можете присвоить значения его элементам:

cell c = ...;
board[i][j] = c;
1

Другие решения

У вас определенно есть доступ из-за вашего неинициализированного вектора. Технически ваш вектор инициализирован, но только как пустой контейнер, вы подразумеваете, что вы должны зарезервировать достаточное количество ячеек, чтобы рассматривать его и содержащийся в нем вектор как двумерный массив и, следовательно, должны либо a) добавить ячейки в цикле b) использовать диапазон конструктор с) использовать конструктор, который принимает количество элементов. Больше информации доступно Вот.

Лучше всегда убедиться, что ваши типы пригодны для использования в конце конструктора. Предпочитайте инициализировать то, что вы можете в списке инициализации конструктора, и прибегайте к использованию области конструктора для всего, что требует больше логики. Если ваш тип не всегда может быть создан полностью, рассмотрите именованный конструктор. По сути, вы просто возвращаете дескриптор из статической функции или функции, не являющейся членом, позволяющей вам вернуть значение часового для неудачного создания (иначе говоря, NULL для указателей).

Похоже, вам нужно подумать о том, как работает система типов C ++.

Если ваш тип «ячейка» не является дескриптором какого-либо типа данных или просто POD type, вы, вероятно, захотите сохранить ссылку на выделенный объект кучи в вашем векторе, а не копию объекта ячейки.

Если ячейка должна обрабатываться как полиморфный тип (вы хотите использовать его в качестве базового класса), вам нужно будет хранить некоторую форму дескриптора в вашем векторе, такую ​​как указатель или, еще лучше, умный указатель.

Если вы используете C ++ 11, вы можете использовать один из новых встроенные умные указатели или вы всегда можете отступить на увеличение.

Ключевым моментом является то, что вы должны предпочесть использовать RAII практики, чтобы избежать висячих ссылок. Хотя в C ++ нет встроенного сборщика мусора, вы можете добиться невероятно стабильного продукта, использующего принципы RAII. Главное, чего следует избегать, — это циклические ссылки, которые можно смягчить, используя слабые ссылки на отношения, где вы не требуете, чтобы референт оставался живым. Типичным примером этого является ситуация, когда у вас есть иерархия объектов, где родительский класс содержит ссылку на детей, которые интернируют, хранят ссылку на родителя. Детям, скорее всего, не понадобится сильная ссылка на родителя, поскольку ожидается, что они выйдут за рамки родительского контроля.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector