xcode C++ 新手,“EXC_BAD_ACCESS”错误我不明白
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15074436/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
New to C++, "EXC_BAD_ACCESS" error I don't understand
提问by mr. knott
I am attempting to translate a 2 dimensional cellular automata from Processing to openFrameworks (C++). I have written classes for the cells and for the game of life functionality. The application builds successfully but crashes immediately with the following error: Thread 1: Program received signal: "EXC_BAD_ACCESS".
我正在尝试将二维元胞自动机从 Processing 转换为 openFrameworks (C++)。我已经为细胞和生命游戏功能编写了类。应用程序成功构建但立即崩溃并出现以下错误:线程 1:程序接收到信号:“EXC_BAD_ACCESS”。
Here's my the header of my game of life class
这是我的人生游戏课程的标题
#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;
};
and here is the implementation:
这是实现:
#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();
}
}
}
the error shows up in the vector.h file, in the GoL header file and where I call the init() method in the GoL implementation. Any help is much appreciated.
该错误显示在 vector.h 文件中、GoL 头文件中以及我在 GoL 实现中调用 init() 方法的位置。任何帮助深表感谢。
回答by juanchopanza
You have an out of bounds access here, because the vector has size 0:
您在这里有越界访问权限,因为向量的大小为 0:
board[rows][cols];
You can initialize the vector in the constructor initialization list like this:
您可以像这样在构造函数初始化列表中初始化向量:
GoL::GoL() : cols(ofGetWidth()/w), rows(ofGetHeight()/w), board(rows, std::vector<cell>(cols))
{
}
That will initialize board
to be size rows
, and each of its elements will be a vector of size cols
. Then you can assign values to its elements:
这将初始化board
为 size rows
,并且它的每个元素都将是一个 size 向量cols
。然后你可以给它的元素赋值:
cell c = ...;
board[i][j] = c;
回答by Matthew Sanders
You definitely have an out of bound access due to your uninitialized vector. Technically your vector is initialized, but only as an empty container, you are implying that you should be reserving enough cells to treat it and its contained vector as a 2d array and thus must either a) add cells in a loop b) use the range constructor c) use the constructor that takes a count for the number of elements. More information is available here.
由于您的向量未初始化,您肯定有越界访问权限。从技术上讲,您的向量已初始化,但仅作为一个空容器,您暗示您应该保留足够的单元格以将其及其包含的向量视为二维数组,因此必须 a) 在循环中添加单元格 b) 使用范围构造函数 c) 使用对元素数量进行计数的构造函数。可在此处获得更多信息。
It is best to always make sure your types are usable by the end of the constructor. Prefer to initialize what you can in the constructor initialization list, and fall back on using the constructor scope for anything that requires more logic. If your type cannot always be constructed fully consider the named constructor idiom. Basically you are just returning a handle from a static or non-member friend function allowing you to return a sentinel value for unsuccessful creation (aka NULL for pointers).
最好始终确保您的类型在构造函数结束时可用。更喜欢在构造函数初始化列表中初始化您可以初始化的内容,并回退使用构造函数范围来处理需要更多逻辑的任何内容。如果您的类型不能总是被完全构造,请考虑命名构造函数惯用语。基本上,您只是从静态或非成员朋友函数返回一个句柄,允许您为不成功的创建返回一个哨兵值(也就是指针的 NULL)。
It sounds like you need to consider how the C++ type system works as well.
听起来您还需要考虑 C++ 类型系统的工作方式。
Unless your type "cell" is a handle to some data type or simply a PODtype you will likely want to store a reference to a heap allocated object in your vector and not a copy of a cell object.
除非您的类型“单元格”是某种数据类型的句柄或只是POD类型,否则您可能希望在向量中存储对堆分配对象的引用,而不是单元格对象的副本。
If cell must be treated like a polymorphic type (you want to use it as a base class) you will need to store some form of handle in your vector such as a pointer or better yet smart pointer.
如果必须将单元格视为多态类型(您想将其用作基类),则需要在向量中存储某种形式的句柄,例如指针或更好的智能指针。
If your using C++11 you can use one of the new built in smart pointersor you can always fallback on boost.
如果您使用 C++11,您可以使用新的内置智能指针之一,或者您始终可以使用boost。
The key point is that you should prefer to use RAIIpractices to avoid dangling references. Although C++ does not have a built in garbage collector, you can achieve an incredibly stable product employing RAII principles. The main thing to avoid is circular references which can be mitigated by employing weak references to relations where you do not require the referent to remain alive. A common example of this is when you have an object hierarchy where a parent class holds a reference to children who intern hold a reference to the parent. The children will likely not need a strong reference to the parent as they will be expected to go out of scope when the parent does.
关键是你应该更喜欢使用RAII实践来避免悬空引用。尽管 C++ 没有内置的垃圾收集器,但您可以使用 RAII 原理实现令人难以置信的稳定产品。要避免的主要事情是循环引用,可以通过对不需要引用保持活动的关系使用弱引用来减轻循环引用。一个常见的例子是当您有一个对象层次结构时,其中父类持有对子类的引用,而实习生则持有对父类的引用。孩子们可能不需要对父级的强引用,因为当父级这样做时,他们将超出范围。