Reputation: 1058
This code works fine in VS2010 but now I am trying to port it to my mac with xcode 4.6 and it's giving me some bad access errors at run time. Basically I have a board class which contains a 2d array of tiles, when I create the board I can access the tiles functions but when I later run my draw function it gives me bad access. Here is a sample of my board class.
Board.h
#include "Tile.h"
class Board
{
private:
//This is the GameBoard of a 2D array of Tiles
Tile *** GameBoard;
void CreateBoard(const int size);
void FillValues();
...
public:
Board(int size);
void DrawBoard();
...
}
Board.cpp
Board::Board(const int size)
{
won=false;
lost=false;
BoardSize =size;
GameBoard = new Tile**[size];
CreateBoard(size);
}
void Board::CreateBoard(const int size)
{
...
FillValues()
}
void Board::FillValues()
{
for(int x=1;x<BoardSize+1;x++)
{
for(int y =1;y<BoardSize+1;y++)
{
if (GameBoard[x][y]->Type()=="NumberTile")
{
int neighbors = CountNeighbours(x,y);
GameBoard[x][y]->SetValue(neighbors);
//This works
}
}
}
}
void Board::DrawBoard()
{
for(int i=0;i<=BoardSize+1;i++)
{
for (int j=0;j<=BoardSize+1;j++)
{
if (GameBoard[i][j]->Type() != "BorderTile") {
GameBoard[i][j]->Draw();
//This does not work, i get the error when it tries to use ->Type()
}
}
}
}
...
I call the functions like this
GI = new Board(SCREEN_SIZE);
GI->DrawBoard();
Upvotes: 1
Views: 617
Reputation: 110718
GameBoard = new Tile**[size];
This just creates an array of Tile**
. You don't yet have any actual Tile
s or even Tile*
s and later, when you're trying to access elements of the array with GameBoard[x][y]->
, you're hitting undefined behaviour.
As you have it, you would need to do this:
GameBoard = new Tile**[size]; // Allocate an array of Tile**
for (int i = 0; i < size; i++) {
GameBoard[i] = new Tile*[size]; // Allocate an array of Tile*
for (int j = 0; i < size; j++) {
GameBoard[i][j] = new Tile(); // Allocate an array of Tile
}
}
However, this is awful. It's three lots of dynamic allocation that you have to remember to tidy up at the end (and tidy up correctly).
A simpler approach would be to just have an 2D array of tiles:
Tile GameBoard[CONSTEXPR_SIZE][CONSTEXPR_SIZE];
Or better yet, use the std::array
container:
std::array<std::array<Tile, CONSTEXPR_SIZE>, CONSTEXPR_SIZE> GameBoard;
Here, the size given has to be a constant expression. If you need it to be dynamically sized, use a std::vector
instead.
In the comments below, you say the size of your array is actually BoardSize+1
. Still, you are iterating over too many elements in both your outer and inner for
loops:
for(int i=0;i<=BoardSize+1;i++)
This should be:
for(int i=0; i<BoardSize+1; i++)
Also in the comments below, you say that Type
returns a char*
. That means you can't do your string comparison like this:
GameBoard[i][j]->Type() != "BorderTile"
This simply performs pointer comparison, since the left operand is a char*
and the right operand is convertible to const char*
. It doesn't compare the strings themselves. Instead, you want:
GameBoard[i][j]->Type() != std::string("BorderTile")
This will force std::string
comparison to be used.
Upvotes: 3