connect4 malloc 错误的复制构造函数

Copy constructor for connect4 malloc errors

我正在尝试编写一个 minimax 算法来解决 connect 4 与 alpha-beta 修剪。我什么都做不到,因为我无法复制游戏板...

默认构造函数:

gameStatus::gameStatus(){
 13     gameData = new long[42];
 14     gameBoard[0] = &(gameData[0]);
 15     gameBoard[1] = &(gameData[7]);
 16     gameBoard[2] = &(gameData[14]);
 17     gameBoard[3] = &(gameData[21]);
 18     gameBoard[4] = &(gameData[28]);
 19     gameBoard[5] = &(gameData[35]);
 20     
 21     int i;
 22     for (i = 0; i < 42; i++)
 23     {
 24       gameData[i] = 0;
 25     }
 26     
 27     currentTurn = 1;
 28     player1Score = 0;
 29     player2Score = 0;
 30     pieceCount = 0;
 31     gameFile = 0;
 32     utilityValue = 0;
 33   }

我的复制构造函数如下:(我尝试在每一个之前使用 'this->',也尝试将第 21/22 行组合成 gameData = g.gameData)

 21   gameStatus(const gameStatus &g){
 22     gameData = new long[42];
 23     gameData = g.gameData;
 24     gameBoard[0] = &(g.gameData[0]);
 25     gameBoard[1] = &(g.gameData[7]);
 26     gameBoard[2] = &(g.gameData[14]);
 27     gameBoard[3] = &(g.gameData[21]);
 28     gameBoard[4] = &(g.gameData[28]);
 29     gameBoard[5] = &(g.gameData[35]);
 30     currentTurn = g.currentTurn;
 31     player1Score = g.player1Score;
 32     player2Score = g.player2Score;
 33     pieceCount = g.pieceCount;
 34     gameFile = g.gameFile;
 35     utilityValue = g.utilityValue;
 36     } 

无论我尝试什么,如果我在 aiPlay 函数中包含此调用:

429     gameStatus tmpGame(currentGame);

事情是这样的。我的举动:

MaxConnect-4 game
Current Board:
 -----------------
 | 0 0 0 0 0 0 0 | 
 | 0 0 0 0 0 0 0 | 
 | 0 0 0 0 0 0 0 | 
 | 0 0 0 0 0 0 0 | 
 | 0 0 0 0 0 0 0 | 
 | 0 0 0 0 1 0 0 | 
 -----------------

CPU移动:

MaxConnect-4 game
Current Board:
 -----------------
 | 0 0 0 0 0 0 0 | 
 | 0 0 0 0 0 0 0 | 
 | 0 0 0 0 0 0 0 | 
 | 0 0 0 0 0 0 0 | 
 | 0 0 0 0 0 0 0 | 
 | 0 0 0 2 1 0 10414574138294272 | 
 -----------------

然后在下一个 CPU 移动中我得到了这个:

malloc:对象 0x7fe521402b50 的 *** 错误:未分配正在释放的指针

您有内存泄漏和错误共享。

gameStatus(const gameStatus &g){
    gameData = new long[42];
    gameData = g.gameData;

这里,你请求了42longs,接收到一个指向新分配数据的指针,并将其存储在gameData中。当你用 g 的数据地址覆盖它时,你负责 delete[]ing 的这个指针立即 丢失,在行 gameData = g.gameData。请记住,复制指针是浅拷贝,而不是深拷贝。在像 gameStatus g2 = g1; 这样的副本之后,两个 游戏将指向相同的 gameData,导致双重删除和可怕的错误。

要解决此问题,请删除行 gameData = g.gameData;,然后遍历 gameData 的条目,将每个 g.gameData[i] 分配给 gameData[i],这将是一个很深的问题复制.

    for (int i = 0; i < 42; ++i){
        gameData[i] = g.gameData[i];
    }

    gameBoard[0] = &(g.gameData[0]);
    gameBoard[1] = &(g.gameData[7]);
    gameBoard[2] = &(g.gameData[14]);
    gameBoard[3] = &(g.gameData[21]);
    gameBoard[4] = &(g.gameData[28]);
    gameBoard[5] = &(g.gameData[35]);

在这里,您将 gameBoard 的条目(我假设它用于方便的数组索引;我无法从您显示的内容中分辨出来)指向 other 游戏的数据,不是你自己的数据。您可能想指向自己的数据。

    gameBoard[0] = &(gameData[0]); // or equivalently, gameData
    gameBoard[1] = &(gameData[7]); // or equivalently, gameData + 7
    gameBoard[2] = &(gameData[14]);
    gameBoard[3] = &(gameData[21]);
    gameBoard[4] = &(gameData[28]);
    gameBoard[5] = &(gameData[35]);

    currentTurn = g.currentTurn;
    player1Score = g.player1Score;
    player2Score = g.player2Score;
    pieceCount = g.pieceCount;
    gameFile = g.gameFile;
    utilityValue = g.utilityValue;
} 

构造函数的其余部分乍一看还不错,但我不能确定。您需要提供所有这些 class 成员的定义才能确定。但假设其中 none 个是原始指针,这应该可以正常工作。

我假设您实现了一个删除数组 gameData.

的析构函数

您正在从您复制的内容中窃取内存。这对于移动构造函数来说可能没问题,但对于复制构造函数来说就不行了。

gameStatus(const gameStatus &g) {
    gameData = new long[42]; // leaked memory

    // g.gameData will be destroyed
    // this->gameData will be equal to a deleted resource
    gameData = g.gameData;

    gameBoard[0] = &(g.gameData[0]);

    // ...
}

你要的是复制值:

gameStatus(const gameStatus &g) {
    gameData = new long[42]; // not leaked

    std::copy(g.gameData, g.gameData + 42, gameData);

    gameBoard[0] = &(gameData[0]);

    // ...
}

这将一个一个地复制值。