C++ Valgrind 错误包括 "Invalid write of size 8",但没有内存泄漏

C++ Valgrind errors including "Invalid write of size 8", but no memory leaks

我做了一个简单的C++国际象棋程序,一直在遇到上述来自valgrind的消息(最后添加):

我每个棋子都有 classes,它们都继承自一个抽象的 class ChessPiece。摘要 class 里面有一个字符串和一个枚举。我还有一个 "Cell" class 知道如何绘制自己,并保存指向 ChessPiece 的指针,该指针保存当前在其上的棋子(如果它为空,则指针为 nullptr)

Board class 是 class,它具有进行移动、检查合法性等的所有逻辑。它具有 Cell class 的向量向量(表示矩阵细胞)。

基本上除了 ChessPieces 之外的所有东西都会在内存中自动分配,并且棋子是使用 "new" 分配的,因此它们是堆的一部分

我在下面包含了相关代码(和 valgrind 报告)。

棋子Class:

ChessPiece::ChessPiece(string asciiCode, Player player, PieceType piece)
    : _asciiCode(asciiCode), _player(player), _piece(piece)
{

}

ChessPiece::ChessPiece()
    :_asciiCode("")
{

}

and also holds several other getter functions

单元格 Class:

ChessPiece * _pieceOccupying = nullptr;

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

Cell::~Cell()
{
    delete _pieceOccupying;
}

Cell::Cell(int row, int col)
    : _row(row), _col(col), _occupied(false)
{
    setColour(); //sets enum according to row and col
}

Cell::Cell(int row, int col, ChessPiece * occupying)
    : _row(row), _col(col), _pieceOccupying(occupying), _occupied(true)
{
    setColour(); //sets enum according to row and col
}

void Cell::setOccupying(ChessPiece * occupying)
{
    if (occupying == nullptr)
    {
        _occupied = false;
    }
    else 
    {
        _pieceOccupying = occupying;
        _occupied = true;
    }  
}

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

}

void Cell::setEmptyCell()
{
    _occupied = false;
    _pieceOccupying = nullptr;
}

棋盘Class:

private vector< vector<Cell> > _board;

Board::Board()
{
    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));
    }

    //Set Rooks
    _board[0][0].setOccupying(new Rook(White));
    _board[0][7].setOccupying(new Rook(White));
    _board[7][7].setOccupying(new Rook(Black));
    _board[7][0].setOccupying(new Rook(Black));

    //Set Knights
    _board[0][1].setOccupying(new Knight(White));
    _board[0][6].setOccupying(new Knight(White));
    _board[7][6].setOccupying(new Knight(Black));
    _board[7][1].setOccupying(new Knight(Black));

    //Set Bishops
    _board[0][2].setOccupying(new Bishop(White));
    _board[0][5].setOccupying(new Bishop(White));
    _board[7][5].setOccupying(new Bishop(Black));
    _board[7][2].setOccupying(new Bishop(Black));

    //Set Queens
    _board[0][3].setOccupying(new Queen(White));
    _board[7][3].setOccupying(new Queen(Black));

    //Set Kings
    _board[0][4].setOccupying(new King(White));
    _board[7][4].setOccupying(new King(Black));
    _whiteKingCell = &_board[0][4];
    _blackKingCell = &_board[7][4];

}

我推断棋盘 class 中的以下功能是有问题的,具体问题似乎是吃另一块(如果我 运行 一个不吃东西的小国际象棋游戏另一块并退出,valgrind 完全没有显示错误):

void Board::actualMove(Cell * srcCell, Cell * destCell, Player playerMoving)
{

    //do actual move
    ChessPiece * destPiece = nullptr;
    bool previousMoved = false;
    destPiece = destCell->getOccupyingPiece();
    destCell->setOccupying(srcCell->getOccupyingPiece());
    destCell->getOccupyingPiece()->setMoved(true);
    srcCell->setEmptyCell();
    delete destPiece;
    destPiece = nullptr;
}

Valgrind 说没有任何内存泄漏,但它说存在无效的读取和写入。我似乎无法理解我在这里做错了什么。该程序运行正常,完全没有任何错误。 我应该为 ChessPiece 创建自己的析构函数吗?

我应该在 Cell 的析构函数中做更多的事情吗?

这是详细的 Valgrind 报告。 感谢所有帮助过的人

Valgrind 报告:

==3526== Invalid write of size 8
==3526==    at 0x403554: ChessPiece::~ChessPiece() (ChessPiece.h:13)
==3526==    by 0x404F43: Cell::~Cell() (Cell.cpp:14)
==3526==    by 0x401CBC: void std::_Destroy<Cell>(Cell*) (stl_construct.h:93)
==3526==    by 0x401C85: void std::_Destroy_aux<false>::__destroy<Cell*>(Cell*, Cell*) (stl_construct.h:103)
==3526==    by 0x401C30: void std::_Destroy<Cell*>(Cell*, Cell*) (stl_construct.h:126)
==3526==    by 0x401BBC: void std::_Destroy<Cell*, Cell>(Cell*, Cell*, std::allocator<Cell>&) (stl_construct.h:151)
==3526==    by 0x401AFE: std::vector<Cell, std::allocator<Cell> >::~vector() (stl_vector.h:415)
==3526==    by 0x401AC6: void std::_Destroy<std::vector<Cell, std::allocator<Cell> > >(std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:93)
==3526==    by 0x401A8F: void std::_Destroy_aux<false>::__destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:103)
==3526==    by 0x401A3A: void std::_Destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:126)
==3526==    by 0x4019C6: void std::_Destroy<std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> > >(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*, std::allocator<std::vector<Cell, std::allocator<Cell> > >&) (stl_construct.h:151)
==3526==    by 0x401908: std::vector<std::vector<Cell, std::allocator<Cell> >, std::allocator<std::vector<Cell, std::allocator<Cell> > > >::~vector() (stl_vector.h:415)
==3526==  Address 0x5a1fda0 is 0 bytes inside a block of size 32 free'd
==3526==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3526==    by 0x404F4B: Cell::~Cell() (Cell.cpp:14)
==3526==    by 0x401CBC: void std::_Destroy<Cell>(Cell*) (stl_construct.h:93)
==3526==    by 0x401C85: void std::_Destroy_aux<false>::__destroy<Cell*>(Cell*, Cell*) (stl_construct.h:103)
==3526==    by 0x401C30: void std::_Destroy<Cell*>(Cell*, Cell*) (stl_construct.h:126)
==3526==    by 0x401BBC: void std::_Destroy<Cell*, Cell>(Cell*, Cell*, std::allocator<Cell>&) (stl_construct.h:151)
==3526==    by 0x401AFE: std::vector<Cell, std::allocator<Cell> >::~vector() (stl_vector.h:415)
==3526==    by 0x401AC6: void std::_Destroy<std::vector<Cell, std::allocator<Cell> > >(std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:93)
==3526==    by 0x401A8F: void std::_Destroy_aux<false>::__destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:103)
==3526==    by 0x401A3A: void std::_Destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:126)
==3526==    by 0x4019C6: void std::_Destroy<std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> > >(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*, std::allocator<std::vector<Cell, std::allocator<Cell> > >&) (stl_construct.h:151)
==3526==    by 0x401908: std::vector<std::vector<Cell, std::allocator<Cell> >, std::allocator<std::vector<Cell, std::allocator<Cell> > > >::~vector() (stl_vector.h:415)
==3526== 
==3526== Invalid read of size 8
==3526==    at 0x4EF14C0: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==3526==    by 0x40356A: ChessPiece::~ChessPiece() (ChessPiece.h:13)
==3526==    by 0x404F43: Cell::~Cell() (Cell.cpp:14)
==3526==    by 0x401CBC: void std::_Destroy<Cell>(Cell*) (stl_construct.h:93)
==3526==    by 0x401C85: void std::_Destroy_aux<false>::__destroy<Cell*>(Cell*, Cell*) (stl_construct.h:103)
==3526==    by 0x401C30: void std::_Destroy<Cell*>(Cell*, Cell*) (stl_construct.h:126)
==3526==    by 0x401BBC: void std::_Destroy<Cell*, Cell>(Cell*, Cell*, std::allocator<Cell>&) (stl_construct.h:151)
==3526==    by 0x401AFE: std::vector<Cell, std::allocator<Cell> >::~vector() (stl_vector.h:415)
==3526==    by 0x401AC6: void std::_Destroy<std::vector<Cell, std::allocator<Cell> > >(std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:93)
==3526==    by 0x401A8F: void std::_Destroy_aux<false>::__destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:103)
==3526==    by 0x401A3A: void std::_Destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:126)
==3526==    by 0x4019C6: void std::_Destroy<std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> > >(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*, std::allocator<std::vector<Cell, std::allocator<Cell> > >&) (stl_construct.h:151)
==3526==  Address 0x5a1fda8 is 8 bytes inside a block of size 32 free'd
==3526==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3526==    by 0x404F4B: Cell::~Cell() (Cell.cpp:14)
==3526==    by 0x401CBC: void std::_Destroy<Cell>(Cell*) (stl_construct.h:93)
==3526==    by 0x401C85: void std::_Destroy_aux<false>::__destroy<Cell*>(Cell*, Cell*) (stl_construct.h:103)
==3526==    by 0x401C30: void std::_Destroy<Cell*>(Cell*, Cell*) (stl_construct.h:126)
==3526==    by 0x401BBC: void std::_Destroy<Cell*, Cell>(Cell*, Cell*, std::allocator<Cell>&) (stl_construct.h:151)
==3526==    by 0x401AFE: std::vector<Cell, std::allocator<Cell> >::~vector() (stl_vector.h:415)
==3526==    by 0x401AC6: void std::_Destroy<std::vector<Cell, std::allocator<Cell> > >(std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:93)
==3526==    by 0x401A8F: void std::_Destroy_aux<false>::__destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:103)
==3526==    by 0x401A3A: void std::_Destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:126)
==3526==    by 0x4019C6: void std::_Destroy<std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> > >(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*, std::allocator<std::vector<Cell, std::allocator<Cell> > >&) (stl_construct.h:151)
==3526==    by 0x401908: std::vector<std::vector<Cell, std::allocator<Cell> >, std::allocator<std::vector<Cell, std::allocator<Cell> > > >::~vector() (stl_vector.h:415)
==3526== 
==3526== Invalid free() / delete / delete[] / realloc()
==3526==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3526==    by 0x404F4B: Cell::~Cell() (Cell.cpp:14)
==3526==    by 0x401CBC: void std::_Destroy<Cell>(Cell*) (stl_construct.h:93)
==3526==    by 0x401C85: void std::_Destroy_aux<false>::__destroy<Cell*>(Cell*, Cell*) (stl_construct.h:103)
==3526==    by 0x401C30: void std::_Destroy<Cell*>(Cell*, Cell*) (stl_construct.h:126)
==3526==    by 0x401BBC: void std::_Destroy<Cell*, Cell>(Cell*, Cell*, std::allocator<Cell>&) (stl_construct.h:151)
==3526==    by 0x401AFE: std::vector<Cell, std::allocator<Cell> >::~vector() (stl_vector.h:415)
==3526==    by 0x401AC6: void std::_Destroy<std::vector<Cell, std::allocator<Cell> > >(std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:93)
==3526==    by 0x401A8F: void std::_Destroy_aux<false>::__destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:103)
==3526==    by 0x401A3A: void std::_Destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:126)
==3526==    by 0x4019C6: void std::_Destroy<std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> > >(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*, std::allocator<std::vector<Cell, std::allocator<Cell> > >&) (stl_construct.h:151)
==3526==    by 0x401908: std::vector<std::vector<Cell, std::allocator<Cell> >, std::allocator<std::vector<Cell, std::allocator<Cell> > > >::~vector() (stl_vector.h:415)
==3526==  Address 0x5a1fda0 is 0 bytes inside a block of size 32 free'd
==3526==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3526==    by 0x404F4B: Cell::~Cell() (Cell.cpp:14)
==3526==    by 0x401CBC: void std::_Destroy<Cell>(Cell*) (stl_construct.h:93)
==3526==    by 0x401C85: void std::_Destroy_aux<false>::__destroy<Cell*>(Cell*, Cell*) (stl_construct.h:103)
==3526==    by 0x401C30: void std::_Destroy<Cell*>(Cell*, Cell*) (stl_construct.h:126)
==3526==    by 0x401BBC: void std::_Destroy<Cell*, Cell>(Cell*, Cell*, std::allocator<Cell>&) (stl_construct.h:151)
==3526==    by 0x401AFE: std::vector<Cell, std::allocator<Cell> >::~vector() (stl_vector.h:415)
==3526==    by 0x401AC6: void std::_Destroy<std::vector<Cell, std::allocator<Cell> > >(std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:93)
==3526==    by 0x401A8F: void std::_Destroy_aux<false>::__destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:103)
==3526==    by 0x401A3A: void std::_Destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:126)
==3526==    by 0x4019C6: void std::_Destroy<std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> > >(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*, std::allocator<std::vector<Cell, std::allocator<Cell> > >&) (stl_construct.h:151)
==3526==    by 0x401908: std::vector<std::vector<Cell, std::allocator<Cell> >, std::allocator<std::vector<Cell, std::allocator<Cell> > > >::~vector() (stl_vector.h:415)
==3526== 
==3526== Invalid read of size 4
==3526==    at 0x4E92655: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==3526==    by 0x4EF14DE: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==3526==    by 0x538D148: __run_exit_handlers (exit.c:82)
==3526==    by 0x538D194: exit (exit.c:104)
==3526==    by 0x5372ECB: (below main) (libc-start.c:321)
==3526==  Address 0x5a1d0b0 is 16 bytes inside a block of size 28 free'd
==3526==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3526==    by 0x4EF14DE: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==3526==    by 0x40356A: ChessPiece::~ChessPiece() (ChessPiece.h:13)
==3526==    by 0x404F43: Cell::~Cell() (Cell.cpp:14)
==3526==    by 0x401CBC: void std::_Destroy<Cell>(Cell*) (stl_construct.h:93)
==3526==    by 0x401C85: void std::_Destroy_aux<false>::__destroy<Cell*>(Cell*, Cell*) (stl_construct.h:103)
==3526==    by 0x401C30: void std::_Destroy<Cell*>(Cell*, Cell*) (stl_construct.h:126)
==3526==    by 0x401BBC: void std::_Destroy<Cell*, Cell>(Cell*, Cell*, std::allocator<Cell>&) (stl_construct.h:151)
==3526==    by 0x401AFE: std::vector<Cell, std::allocator<Cell> >::~vector() (stl_vector.h:415)
==3526==    by 0x401AC6: void std::_Destroy<std::vector<Cell, std::allocator<Cell> > >(std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:93)
==3526==    by 0x401A8F: void std::_Destroy_aux<false>::__destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:103)
==3526==    by 0x401A3A: void std::_Destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:126)
==3526== 
==3526== Invalid write of size 4
==3526==    at 0x4E9265B: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==3526==    by 0x4EF14DE: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==3526==    by 0x538D148: __run_exit_handlers (exit.c:82)
==3526==    by 0x538D194: exit (exit.c:104)
==3526==    by 0x5372ECB: (below main) (libc-start.c:321)
==3526==  Address 0x5a1d0b0 is 16 bytes inside a block of size 28 free'd
==3526==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3526==    by 0x4EF14DE: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==3526==    by 0x40356A: ChessPiece::~ChessPiece() (ChessPiece.h:13)
==3526==    by 0x404F43: Cell::~Cell() (Cell.cpp:14)
==3526==    by 0x401CBC: void std::_Destroy<Cell>(Cell*) (stl_construct.h:93)
==3526==    by 0x401C85: void std::_Destroy_aux<false>::__destroy<Cell*>(Cell*, Cell*) (stl_construct.h:103)
==3526==    by 0x401C30: void std::_Destroy<Cell*>(Cell*, Cell*) (stl_construct.h:126)
==3526==    by 0x401BBC: void std::_Destroy<Cell*, Cell>(Cell*, Cell*, std::allocator<Cell>&) (stl_construct.h:151)
==3526==    by 0x401AFE: std::vector<Cell, std::allocator<Cell> >::~vector() (stl_vector.h:415)
==3526==    by 0x401AC6: void std::_Destroy<std::vector<Cell, std::allocator<Cell> > >(std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:93)
==3526==    by 0x401A8F: void std::_Destroy_aux<false>::__destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:103)
==3526==    by 0x401A3A: void std::_Destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:126)
==3526== 
==3526== Invalid free() / delete / delete[] / realloc()
==3526==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3526==    by 0x4EF14DE: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==3526==    by 0x538D148: __run_exit_handlers (exit.c:82)
==3526==    by 0x538D194: exit (exit.c:104)
==3526==    by 0x5372ECB: (below main) (libc-start.c:321)
==3526==  Address 0x5a1d0a0 is 0 bytes inside a block of size 28 free'd
==3526==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3526==    by 0x4EF14DE: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==3526==    by 0x40356A: ChessPiece::~ChessPiece() (ChessPiece.h:13)
==3526==    by 0x404F43: Cell::~Cell() (Cell.cpp:14)
==3526==    by 0x401CBC: void std::_Destroy<Cell>(Cell*) (stl_construct.h:93)
==3526==    by 0x401C85: void std::_Destroy_aux<false>::__destroy<Cell*>(Cell*, Cell*) (stl_construct.h:103)
==3526==    by 0x401C30: void std::_Destroy<Cell*>(Cell*, Cell*) (stl_construct.h:126)
==3526==    by 0x401BBC: void std::_Destroy<Cell*, Cell>(Cell*, Cell*, std::allocator<Cell>&) (stl_construct.h:151)
==3526==    by 0x401AFE: std::vector<Cell, std::allocator<Cell> >::~vector() (stl_vector.h:415)
==3526==    by 0x401AC6: void std::_Destroy<std::vector<Cell, std::allocator<Cell> > >(std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:93)
==3526==    by 0x401A8F: void std::_Destroy_aux<false>::__destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:103)
==3526==    by 0x401A3A: void std::_Destroy<std::vector<Cell, std::allocator<Cell> >*>(std::vector<Cell, std::allocator<Cell> >*, std::vector<Cell, std::allocator<Cell> >*) (stl_construct.h:126)
==3526== 
==3526== 
==3526== HEAP SUMMARY:
==3526==     in use at exit: 0 bytes in 0 blocks
==3526==   total heap usage: 292 allocs, 294 frees, 11,462 bytes allocated
==3526== 
==3526== All heap blocks were freed -- no leaks are possible
==3526== 
==3526== For counts of detected and suppressed errors, rerun with: -v
==3526== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)

Cell 打破 Rule of Three。它尝试 "own" 原始指针,在其析构函数中删除其目标,但无法正确复制,因此两个 Cell 对象都会尝试删除相同的 ChessPiece.

选项是:

  • 如果单元格应该 "own" 片段,则使用智能指针(或编写复制构造函数和复制赋值运算符来正确处理原始指针);
  • 不要让单元格尝试删除该片段,如果它不应该 "own" 它;
  • 使用 boost::optional 之类的东西,允许单元格选择性地包含一个没有动态分配的部分。