【问题标题】:C++ Instance of object Unable to Read memory对象的 C++ 实例无法读取内存
【发布时间】:2015-03-06 13:54:10
【问题描述】:

我需要一些有关 c++ 和对象\引用\指针的帮助。我正在编写一个简单的国际象棋程序,它有几个类。特别是我对以下两个类 Board 和 Cell 有疑问:

棋盘上有一个 Cells 向量的向量(基本上是一个矩阵)。每个单元格都有一个指向当前占用它的块的指针。

class Board
{
public:
    Board();
    void drawBoard();
    bool makeMove(int startRow, int startCol, int destRow, int destCol);
private:
    vector< vector<Cell> > _board;
    void initBoard();
    void initPieces();
};

Board::Board()
{
    initBoard();
}

void Board::initBoard()
{

    for (int i = 0; i < BOARD_SIZE; i++)
    {
        vector<Cell> row; //create empty row
        for (int j = 0; j < BOARD_SIZE; j++)
        {
            row.push_back((Cell(i, j)));
        }
        _board.push_back(row);
    }

    initPieces();
}

void Board::initPieces()
{
    //Set Pawns
    for (int i = 0; i < BOARD_SIZE; i++)
    {
        _board[1][i].setOccupying(new Pawn(White));
        _board[6][i].setOccupying(new Pawn(Black));
    }
}

void Board::drawBoard()
{

    drawLettersCoord();
    for (int i = BOARD_SIZE-1; i >= 0; i--)
    {
        std::cout << i + 1 << " ";
        for (int j = 0; j < BOARD_SIZE; j++)
        {       
            _board[i][j].draw();
        }
        std::cout << " " << i + 1 << std::endl;
    }
    std::cout << "\n";

}

bool Board::makeMove(int startRow, int startCol, int destRow, int destCol)
{
    _board[startRow][startCol].getOccupyingPiece()->isLegalMove(
        startRow, startCol, destRow, destCol);
    return true;
}

这是 Cell 类:

class Cell
{
public:
    Cell();
    Cell(int row, int col);
    Cell(int row, int col, ChessPiece * occupying);
    void draw();
    ChessPiece * getOccupyingPiece();
    void setOccupying(ChessPiece *occupying);
private:
    int _row;
    int _col;
    bool _occupied;
    ChessPiece * _pieceOccupying;
};

Cell::Cell()
    :Cell(0, 0)
{
    setColour();
}

Cell::Cell(int row, int col)
    : _row(row), _col(col), _occupied(false)
{
    setColour();
}

Cell::Cell(int row, int col, ChessPiece * occupying)
    : _row(row), _col(col), _pieceOccupying(occupying), _occupied(true)
{
    setColour();
}

void Cell::setOccupying(ChessPiece *occupying)
{
    _occupied = true;
    _pieceOccupying = occupying;
}
void Cell::draw()
{

    int foregroundText;
    if (!_occupied)
    {
        foregroundText = 37;
    }
    else
    {
        foregroundText = _pieceOccupying->getPlayer();
    }
    cout << "\33[" << foregroundText << ";" << _colour << "m"
         << (_occupied ? _pieceOccupying->getPieceCode(): " ") << "\33[0m";
}

ChessPiece * Cell::getOccupyingPiece()
{
    return _pieceOccupying;
}

当我运行游戏时,我通过调用来创建并绘制一个新棋盘

Board _board;
_board.drawBoard();

绘图似乎可以正常工作,没有任何问题。

但是,当我打电话时

_board.makeMove(1,0,2,0);

为了检查棋子是否可以进行这样的移动,我得到了一个内存错误。在调试时,我看到被调用的 Cell 对象中有垃圾而不是实际数据。当我尝试查看指向占用块的指针时,它显示“无法读取内存”,所以当我调用占用块的 isLegalMove 函数时,它会崩溃。

我似乎无法找出问题所在。我不明白为什么向量内的单元格中会有垃圾,它是在类中定义的(没有新的),所以根据我的理解,只要板的当前实例还活着,它就应该可用。

谁能说明我做错了什么?

【问题讨论】:

  • 很可能是Rule of Three 问题。
  • @πάνταῥεῖ 在这种情况下,类似乎遵循零规则。
  • @Angew 是的,看起来你提到的缺少初始化。

标签: c++ pointers object c++11 reference


【解决方案1】:
  1. 并非所有Cell 的构造函数都初始化_occupied_pieceOccupying,这意味着它们在某些Cell 对象中可能有垃圾值。

  2. 此外,您的 makeMove 无条件取消引用 getOccupyingPiece() - 它不检查 null。

  3. 最后,你的棋盘上只有棋子,这意味着 (0, 0) 不包含棋子 - 因为 1.,Cell 对象在其 _pieceOccupying 中包含一个垃圾值,所以你访问随机内存并崩溃。

【讨论】:

  • 您好,感谢您的回答!即使我将所有棋子都放在棋盘上,并且当我使用正确的棋子坐标调用该方法时,似乎也会发生内存错误。 (我只是不想把整个棋盘初始化,因为它类似于棋子的制作方式)
  • @user475680 我已尽力使用您提供给我们的信息。如果这没有帮助,请提供更完整的信息 - MCVE。那是 minimal 代码,我可以直接复制并粘贴到例如ideone 并观察与您相同的行为。
  • 感谢您的帮助。它现在似乎工作正常,奇怪的是。我可能在调试或其他事情中错误地取消了它的引用。除了在开始时分配 nullptr 并按照您的建议检查空值外,我没有进行任何更改。我只是对 C++ 内存分配还不是很满意,所以我想也许我做错了什么或有问题
猜你喜欢
  • 2019-10-21
  • 1970-01-01
  • 1970-01-01
  • 2016-07-25
  • 2011-12-07
  • 2016-03-13
  • 2010-12-29
  • 2019-12-14
  • 1970-01-01
相关资源
最近更新 更多