Why do I get a segmentation fault for assigning a unique pointer to a nullptr?

63 views Asked by At

I try to make an undo function for an atomic chess game in c++. If it is a caputre this is how the function figures should move, so the squares around the capture square should be empty if it is not a pawn and the capture square is also empty after the capture.

if (is_capture) {
    if (c.board[dest_row][dest_file]->representation() == 'k' ||
        c.board[dest_row][dest_file]->representation() == 'K') {
      c.board[dest_row][dest_file] = std::move(c.board[src_row][src_file]);
      c.board[dest_row][dest_file] = nullptr;
      won = 1;
    } else {
      c.board[dest_row][dest_file] = std::move(c.board[src_row][src_file]);
      c.board[dest_row][dest_file] = nullptr;
    }

    if ((dest_row + 1) < 8) {
      if (c.board[dest_row + 1][dest_file] != nullptr &&
          (c.board[dest_row + 1][dest_file]->representation() != 'p' &&
           c.board[dest_row + 1][dest_file]->representation() != 'P')) {
        if (c.board[dest_row + 1][dest_file]->representation() == 'k' ||
            c.board[dest_row + 1][dest_file]->representation() == 'K') {
          won = 1;
        }
        c.board[dest_row + 1][dest_file] = nullptr;
      }
    } .... 

Now the undo function works fine for normal moves and for captures if it is not a nullptr after the capture. I tried commenting out this line c.board[dest_row][dest_file] = nullptr; and then it was a normal capture that was possible to undo. I also tried setting it directly to a nullptr and got also a segmentation fault. So I think it is related to the nullptr, but I don't understand why I cannot put a new unique pointer on the nullptr. This is the undo function

void chess::undo(chess &c, vector<string> &move_history,
                 vector<piece> &last_captured) {
  string undo_move;

  if (!move_history.empty()) {
    undo_move = move_history.back();
  }

  int dest_move_undo_file= undo_move[1] - 'a';
  int dest_move_undo_row = undo_move[2] - '1';
  int src_move_undo_file;
  int src_move_undo_row;
  if (undo_move[3] == 'x') {
    src_move_undo_row = undo_move[5] - '1';
    src_move_undo_file = undo_move[4] - 'a';
  } else {
    src_move_undo_row = undo_move[4] - '1';
    src_move_undo_file = undo_move[3] - 'a';
  }

  if (undo_move[undo_move.length() - 2] == '=') {
    c.board[dest_move_undo_row][dest_move_undo_file] = std::make_unique<piece>(
        c.board[src_move_undo_row][src_move_undo_file]->p, shape::pawn);
  } else {
    c.board[dest_move_undo_row][dest_move_undo_file] = std::make_unique<piece>(
        c.board[src_move_undo_row][src_move_undo_file]->p, c.board[src_move_undo_row][src_move_undo_file]->s);
  }

  c.board[src_move_undo_row][src_move_undo_file] = nullptr;

  if (undo_move[3] == 'x') {
   
      player captured_player = last_captured.back().p;
      shape captured_shape = last_captured.back().s;
      c.board[src_move_undo_row][src_move_undo_file] =
          std::make_unique<piece>(captured_player, captured_shape);
      last_captured.pop_back();}

  move_history.pop_back();
  c.next_to_move =
      c.next_to_move == player::white ? player::black : player::white;
} 

and before the move is done it is stored in these vectors to make the undo possible

move_history.push_back(move);
  if (dest_square != nullptr) {
      last_captured.push_back(*dest_square);
  }

I wanted to try debugging with valgrind but I was not able to install it on macos and gdb seems also not to work on M1 chips, so I have no idea how to find the problem.

0

There are 0 answers