I'm working on a chess engine in C. I've found a memory leak when running Valgrind:
==18455== 64 bytes in 1 blocks are definitely lost in loss record 9 of 199
==18455== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18455== by 0x40451C: copyGame (Chess.c:1093)
==18455== by 0x401356: addToList (Chess.c:213)
==18455== by 0x4014A0: register_move (Chess.c:245)
==18455== by 0x4019C3: getPawnMoves (Chess.c:300)
==18455== by 0x40119A: getSquareMoves (Chess.c:169)
==18455== by 0x404F88: evaluate (MiniMax.c:69)
==18455== by 0x405D93: alphaBetaMax (MiniMax.c:290)
==18455== by 0x405CF6: alphaBetaMax (MiniMax.c:274)
==18455== by 0x405CF6: alphaBetaMax (MiniMax.c:274)
==18455== by 0x405EC1: getBestMove (MiniMax.c:307)
==18455== by 0x403933: computerTurn (Chess.c:852)
What's happening here is this: During the computer turn, after the minimax algorithm reaches depth 0 it calls evaluate. Evaluate looks at all the possible moves of the current player and adds them to a list. To check if a move can be added to that list, the move is performed on a copy of the current game and the program checks if the current player is NOT in check (legal move). Then the move can be added.
From this I get that there seems to be a problem with copyGame:
void copyGame(game_t game, game_t *copy)
{
int i = 0, j = 0;
copy->data = (int*)malloc(sizeof(int)* 16);
checkMalloc(copy->data);
copy->board = (board_t)malloc(sizeof(char*)*BOARD_SIZE); // board_t is char**
checkMalloc(copy->board);
for (i = 0; i<BOARD_SIZE; i++)
{
copy->board[i] = (char*)malloc(sizeof(char)*BOARD_SIZE);
checkMalloc(copy->board[i]);
}
for (i = 0; i<16; i++)
{
copy->data[i] = game.data[i]; //data contains additional information about the game
}
for (i = 0; i<BOARD_SIZE; i++)
for (j = 0; j<BOARD_SIZE; j++)
{
copy->board[i][j] = game.board[i][j];
}
}
And here is the function that calls copyGame:
move_t* addToList(game_t game, move_t* list, move_t * move, int color)
{
int kx, ky;
game_t copy;
copyGame(game, ©);
makeMove(©, *move);
kx = copy.data[2];
ky = copy.data[3];
if (color)
{
kx = copy.data[0];
ky = copy.data[1];
}
if (isAttacked(©, kx, ky, color) == 0) // if curplayer's king isn't attacked
{
move->next = list;
list = move;
}
else
{
free(move);
}
freeGame(copy);
return list;
}
But I suspect the problem might be with freeGame:
void freeGame(game_t game)
{
int i = 0;
for (i = 0; i<BOARD_SIZE; i++)
{
free(game.board[i]);
}
free(game.data);
}
I just don't understand the error as presented by Valgrind, and would appreciate if someone with more experience in C could help. Thanks for reading.
You are freeing game.data
as well as each game.board[i]
. But you are not freeing the game.board
itself (the second malloc
in copyGame
). Add this to the end of freeGame
:
free(game.board);