【问题标题】:C++ Valgrind errors including "Invalid write of size 8", but no memory leaksC++ Valgrind 错误,包括“大小为 8 的无效写入”,但没有内存泄漏
【发布时间】:2015-01-13 12:33:31
【问题描述】:

我做了一个简单的 C++ Chess 程序,并且一直在体验 valgrind 的上述消息(在末尾添加):

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

Board 类是具有移动、检查合法性等所有逻辑的类。它具有 Cell 类的向量向量(表示单元矩阵)。

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

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

国际象棋类:

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

}

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

}

and also holds several other getter functions

细胞类别:

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;
}

板级:

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];

}

我已经推断出 Board 类中的以下函数是有问题的,特别是问题似乎是吃另一块(如果我运行一个小型国际象棋游戏而不吃另一块并退出,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)

【问题讨论】:

  • 你能告诉我 setEmptyCell() 吗?
  • @hidrargyro 是的,刚刚添加进去

标签: c++ memory memory-management memory-leaks valgrind


【解决方案1】:

Cell 打破了Rule of Three。它试图“拥有”一个原始指针,在其析构函数中删除其目标,但不能正确复制,因此两个 Cell 对象都将尝试删除相同的 ChessPiece

选项是:

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

【讨论】:

  • 关于第二个选项:这是否意味着基本上从 Cell 类中删除析构函数,然后在 Board 的析构函数中遍历每个单元格,检索指向 ChessPiece 的指针并将其删除?
  • @user475680:这当然涉及删除析构函数。与将原始指针从单元格中拉出相比,我会使用一种不那么笨拙的方式来管理所有权,并摆脱所有原始的new 表达式;也许将它们全部存储在一个容器中(如std::vector&lt;std::unique_ptr&lt;Piece&gt;&gt;),为每个单元格提供指向其中一个单元格的指针,并确保容器比单元格更长寿。但第一种或第三种选择可能会更好。
  • 谢谢!我按照您的说明进行了一些更改,现在效果很好,没有任何 valgrind 错误!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-25
  • 2016-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多