C++新手,我不明白"EXC_BAD_ACCESS"错误

New to C++, "EXC_BAD_ACCESS" error I don't understand

本文关键字:EXC ACCESS 错误 BAD 明白 新手 C++      更新时间:2023-10-16

我正在尝试将一个二维元胞自动机从Processing转换为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头文件以及我在GoL实现中调用init((方法的地方。非常感谢您的帮助。

这里有一个越界访问,因为向量的大小为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;

由于您的向量未初始化,您肯定有一个越界访问。从技术上讲,你的向量是初始化的,但只是作为一个空容器,这意味着你应该保留足够的单元来将它及其包含的向量视为一个2d数组,因此必须a(在循环中添加单元b(使用范围构造函数c(使用对元素数量进行计数的构造函数。更多信息请点击此处。

最好始终确保您的类型在构造函数结束时可用。更喜欢在构造函数初始化列表中初始化您可以初始化的内容,并将构造函数范围用于任何需要更多逻辑的内容。如果您的类型不能始终构造,请充分考虑命名构造函数习惯用法。基本上,您只是从静态或非成员朋友函数返回一个句柄,允许您为不成功的创建返回一个sentinel值(也称为NULL,表示指针(。

听起来您还需要考虑C++类型的系统是如何工作的。

除非您的类型"cell"是某个数据类型的句柄,或者只是POD类型,否则您可能希望在向量中存储对堆分配对象的引用,而不是cell对象的副本。

若单元格必须像多态类型一样处理(您希望将其用作基类(,则需要在向量中存储某种形式的句柄,例如指针或更好的智能指针。

如果你使用C++11,你可以使用一个新的内置智能指针,或者你可以随时使用boost。

关键的一点是,您应该更喜欢使用RAII实践来避免悬挂引用。尽管C++没有内置的垃圾收集器,但您可以使用RAII原理实现一个非常稳定的产品。主要要避免的是循环引用,这可以通过使用对关系的弱引用来减轻,在这种关系中,您不需要引用保持活动。一个常见的例子是,当您有一个对象层次结构时,父类持有对子级的引用,而子级则持有对父级的引用。孩子们可能不需要对父母的有力引用,因为当父母这样做时,他们会超出范围。