Home > Software design >  Array of objects being corrupted after using cout
Array of objects being corrupted after using cout

Time:09-17

After a few days of my question being closed, and my edits that would answer all of the questions in the comments not being approved, I have decided to re-post with a few changes.

I am new to c , but I am an experienced programmer. I am trying to create a chess engine, as I have done it in python but I want it faster. I am storing my chess board as a 2d array of Piece pointers.

chessBoard.h

#include <iostream>
#include "pieces.h"

class Chess
{
private:
    Piece* board[8][8] = {};
public:
    Chess();
    void print_board();
};

pieces.h

enum PieceType {
    pawn, knight, bishop, rook, queen, king
};

enum Colour {
    white, black
};

class Piece {
protected:
    PieceType pieceType;
    Colour colour;
public:
    char symbol;
    Piece(Colour colour);
};

class Pawn : public Piece {
public:
    Pawn(Colour colour);
};

// The rest of the pieces are defined in the same way

pieces.cpp

#include "pieces.h"

Piece::Piece(Colour colour) {
    this->colour = colour;
}

Pawn::Pawn(Colour colour) : Piece(colour) {
    this->pieceType = pawn;
    this->symbol = (colour == white) ? 'P' : 'p';
}

// The rest of the pieces constructors are the same 

chessBoard.cpp

Chess::Chess()
{
    // The back row of black pieces
    Rook bq_r(black);
    Knight bq_n(black);
    Bishop bq_b(black);
    Queen bq_q(black);
    King bk_k(black);
    Bishop bk_b(black);
    Knight bk_n(black);
    Rook bk_r(black);

    board[0][0] = &bq_r;
    board[0][1] = &bq_n;
    board[0][2] = &bq_b;
    board[0][3] = &bq_q;
    board[0][4] = &bk_k;
    board[0][5] = &bk_b;
    board[0][6] = &bk_n;
    board[0][7] = &bk_r;
}

void Chess::print_board() {
    for (int i = 0; i < 8; i  ) {
        for (int j = 0; j < 8; j  ) {
            if (board[i][j]) {
                std::cout << board[i][j]->symbol;
                std::cout << " ";
            } else {
                std::cout << ". ";
            }
        }
        std::cout << std::endl;
    }
}

main.cpp

#include "chessBoard.h"

int main()
{
    Chess chess;
    chess.print_board();
    return 1;
}

I understand this is a lot of code, and I wish I could post only the relevant information, but unfortunately I have no clue what the problem was, and most of the comments on my last post asked for more info. If needed the complete code, it can be found here: Screenshot from when it works

This is a screenshot from after the first iteration, after encountering the std::cout on line 4 of the printBoard() function.

Screenshot from after it doesnt

I have been stuck on this problem for 2 days, researching and debugging, and I've found nothing. I'm sure it's something simple I'm doing wrong, I just can't find it. Please comment if you need any more info.

Thank you

CodePudding user response:

The accepted answer fixes the object lifetime problem by using dynamic allocation to create heap objects, but it should be noted that polymorphism on a base class pointer doesn't require dynamic allocation (I'm assuming you intend to add virtual functions later).

The various derived pieces could simply be data members of the Chess object, which often offers better performance and fewer pitfalls than dynamic allocation (moving the pointers around the board correctly may also be needlessly cumbersome with unique_ptr):

class Chess {
private:
    Piece* board[8][8] = {};

    Rook m_white_rook;
    Knight m_white_knight;
    // ...all pieces here...

public:
    Chess() : 
        m_white_rook(Colour::white), 
        m_white_knight(Colour::white),
        // ...initialize pieces here...
    {
        board[0][0] = &m_white_rook;
        board[0][1] = &m_white_knight;
        // ...assign simple, non-owning pointers to the board...
    }
};

CodePudding user response:

The objects bq_r etc. defined in your Chess::Chess() constructor have their lifetimes end when the constructor finishes, so the array is full of dangling pointers which can't validly be used.

I'd recommend instead:

#include <memory>

class Chess
{
private:
    std::unique_ptr<Piece> board[8][8] = {};
public:
    Chess();
    void print_board();
};

Chess::Chess()
{
    board[0][0] = std::make_unique<Rook>(black);
    board[0][1] = std::make_unique<Knight>(black);
    board[0][2] = std::make_unique<Bishop>(black);
    board[0][3] = std::make_unique<Queen>(black);
    board[0][4] = std::make_unique<King>(black);
    board[0][5] = std::make_unique<Bishop>(black);
    board[0][6] = std::make_unique<Knight>(black);
    board[0][7] = std::make_unique<Rook>(black);

    for (auto& pawn_pos : board[1])
         pawn_pos = std::make_unique<Pawn>(black);

    // ...
}

Since the unique_ptrs will clean up by deleting a pointer to base class Piece which actually points at other class types, that class needs a virtual destructor:

class Piece {
public:
    // ...
    virtual ~Piece() = default;
};
  • Related