0

I'm programming a board game. When I call the constructor (with parameters) for the game, the program segfaults.

Main file:

#include <iostream>
#include "game.h"
using namespace std;

int main(){
    int p_count = 2;
    Game g(p_count);
    //g.play(); 
}

Game Header:

#ifndef GAME_H_
#define GAME_H_
#include    <iostream>
#include    "board.h"
#include    "player.h"

using namespace std;

class Game{

private:
    Board               b;
    int                 moves, gamers;
    Player              players[10];
    bool                running;

public:
    Game                        (int p_count);
    void    setup               ();
    void    play                ();
    void    report_score        ();
    bool    in_mate             (Player p);
    bool    in_check            (Player p);
};

Game Constructor:

#include "game.h"

Game::Game(int p_count){
    running = true;
    moves = 0;
    gamers = p_count;
    }

Board header

#ifndef BOARD_H_
#define BOARD_H_
#include    <iostream>

using namespace std;

class Piece;

class Board{

private:
    static const int SIZE = 8;
    Piece *board[SIZE][SIZE];

public:
    Board               ();

};


#endif /* BOARD_H_ */

Board constructor

#include "board.h"
#include "piece.h"
Board::Board(){
    bool b = false;
    for (int i=0; i<SIZE; i++){
        for(int j=0; j<SIZE;j++){
            board[i][j]->set_status(b);
        }
    }
}

Player header

#ifndef PLAYER_H_
#define PLAYER_H_
#include <iostream>
#include    "board.h"
#include    "piece.h"

using namespace std;

class Player{

private:
    static const int NUM = 16;
    Piece pieces[NUM];
    int side;
public:
    Player              ();
    Player              (int p);
#endif

Player constructor

#include "player.h"
Player::Player(){
    side = 0;
}

Piece header

#ifndef PIECE_H_
#define PIECE_H_
#include <iostream>
#include "board.h"

using namespace std;

class Board;

struct location{
    int row;
    int col;
};

class Piece{

private:
    location    pos_moves[50], loc;
    char        type;
    bool        status;
    int         moved, team;

public:
    Piece                   ();
    Piece                   (int piece_num, int bel);
    void    set_status      (bool b);
};

#endif /* PIECE_H_ */

Piece implementation

#include "piece.h"
Piece::Piece(){
    status = false;
    team = 0;
    moved = 0;
    type = 'A';
}

void Piece::set_status(bool b){
    status = b;
}

I call some functions from within the constructor that initialize the unused variables, but the program crashes regardless of whether or not they're included.

Jordan
  • 53
  • 6
  • 3
    What do `Player` and `Board` constructors do? – StenSoft Jul 27 '15 at 01:40
  • Player is what I mentioned is called in the constructor, which calls board, and between them do a lot to set up the game. But like I said commenting them out of the constructor still causes it to segfault so I figured they weren't a source of the problem. – Jordan Jul 27 '15 at 01:45
  • Their constructors are called implicitely even when you comment explicit initialization out. Also note that if you initialize them with `b = Board(…)` in the body of the constructor, it will still call default constructors before that. You should use [initializer list](http://en.cppreference.com/w/cpp/language/initializer_list) instead. – StenSoft Jul 27 '15 at 01:47
  • Oh I didn't think of that. So I should probably check those constructors as well? – Jordan Jul 27 '15 at 01:50
  • You need to show us the default constructors for `Board` and `Player`. – clstrfsck Jul 27 '15 at 01:51
  • It's difficult to answer if you didn't post the entire code. Your game constructor has no link to any other classes besides setting some class variables. Your Board class looks suspicious with the with Piece* board[SIZE][SIZE] without initialisation and what is "set_status"? – John Yang Jul 27 '15 at 02:19

2 Answers2

3

One problem that I see is that you have defined board as an array of pointers, not objects,

  Piece *board[SIZE][SIZE];

and then you proceed to use board in Game::Game() as though board points to valid objects.

Board::Board(){
   bool b = false;
   for (int i=0; i<SIZE; i++){
      for(int j=0; j<SIZE;j++){

         // Problem.
         // board[i][j] has not been initialized
         // to point to any valid object.
         board[i][j]->set_status(b);
      }
   }
}

You can resolve that by making board an array of objects.

  Piece board[SIZE][SIZE];

or making sure that you allocate memory each element of the array before using them.

Board::Board(){
   bool b = false;
   for (int i=0; i<SIZE; i++){
      for(int j=0; j<SIZE;j++){

         // Allocate memory for the element
         // of the array.
         board[i][j] = new Piece;
         board[i][j]->set_status(b);
      }
   }
}

I recommend using an array of objects. Then, you won't have to worry about dealing with memory allocation and deallocation. If you use an array of pointers, please read The Rule of Three.

Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Also I dont see a set_status(bool) member function of Piece in its declaration. – Emile Vrijdags Jul 27 '15 at 02:22
  • That is essentially where the problem arose. I initially had everything as objects without pointers. It worked for a while but as a I developed more of the code I realized I needed forward declarations for "board" and "piece" (I'm relatively new to programming), When I added that in to the board and piece headers, a compiler error told me that Piece board[SIZE][SIZE] has "an incomplete type". The solution to that was to declare it as a pointer. Like you said its not ideal to use pointers but I don't know of any other solution. Thanks for your help. – Jordan Jul 27 '15 at 02:31
  • @Jordan, you can use either approach to get your program working. Understand the pros and cons of each approach. You can even implement it both ways to see which one you like better :) – R Sahu Jul 27 '15 at 02:35
  • @R Sahu I would like to use the object method, but it won't compile if i change "Piece *board[SIZE][SIZE]" to "Piece board[SIZE][SIZE]". It said "field board has an incomplete type" – Jordan Jul 27 '15 at 02:49
  • @Jordan, you can `#include "piece.h"` in `board.h` to overcome that problem. – R Sahu Jul 27 '15 at 02:51
  • @R Sahu hahaha, When I include "piece.h" in "board.h", it still doesn't compile. I think it might be because then piece and board would be included in each other. Wouldn't that cause an infinite loop? – Jordan Jul 27 '15 at 02:59
  • @Jordan, it won't cause infinite loop because of the include guards but that is not good. You'll have to use forward declaration in one. I think it will be adequate to use forward declaration of `Board` in `"piece.h"`. – R Sahu Jul 27 '15 at 03:00
  • @R Sahu So I am including piece and board in each other, and having forward declarators of both in each other, and it's still not compiling. :( Same error as before – Jordan Jul 27 '15 at 03:08
  • @Jordan, `Piece` does not use `Board` at all. You don't need `#include "board.h"` or `class Board;` in `"piece.h"`. – R Sahu Jul 27 '15 at 03:10
  • @R Sahu I have some public functions in "piece.h" that take a Board as a parameter. I didn't include them above because they weren't required for the compiling – Jordan Jul 27 '15 at 03:14
  • @Jordan, Are those pointers, references, objects? Of they are pointers or references you can remove `#include "board.h"` from `piece.h` and just use the forward declaration, `class Board;`. – R Sahu Jul 27 '15 at 03:16
  • @R Sahu So they are references. But I don't include "board.h" but have the forward declaration. This causes a compiler error on the forward declaration "class Board;". It just says "forward declaration of 'class Board'". For reference I'm using eclipse with the generic gnu compiler – Jordan Jul 27 '15 at 03:34
  • @Jordan, that does not sound right. You should be able to use references to `Board` with just a forward declaration. – R Sahu Jul 27 '15 at 03:48
  • @R Sahu could I be missing a namespace or not including something i need to be? Otherwise I think I just have to stick with using pointers :\ – Jordan Jul 27 '15 at 04:07
  • A remark regarding forward declaration: it introduces a name that can be used as reference or pointer in a declaration as the compiler has no need to know the size nor members of the forward declared class/type at that point. But when a function definition uses e.g. a member function of the forward declared type, the definition has to be known at that point, meaning the forwarded type should be included before actually using it. So if you want to forward declare Board in Piece, you still need to include "board.h" in piece.cpp where you will be using Board. – Emile Vrijdags Jul 27 '15 at 11:40
  • my previous remark is the only thing I could think of why you got the "forward declaration of 'class Board'" error message. – Emile Vrijdags Jul 27 '15 at 11:48
0

board is a 2-d array of the pointer of Piece, you should new it before use it in Board's ctor:

Board::Board(){
    bool b = false;
    for (int i=0; i<SIZE; i++){
        for(int j=0; j<SIZE;j++){
            board[i][j] = new Piece;  // add it here
            board[i][j]->set_status(b);
        }
    }
}

BTW, don't forget to delete the pointers, maybe in Board's dtor.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405