C++象棋引擎接收用户移动指令时触发写访问错误求助
开发基础C++象棋引擎时,通过用户输入字符串(例如输入1144代表从第1列第1行移动到第4列第4行)执行移动操作,触发写访问错误,Visual Studio调用栈如下:
ChessUltimate.exe!std::_String_val<std::_Simple_types
>::_Large_string_engaged() Line 2282 C++
ChessUltimate.exe!std::_String_val<std::_Simple_types>::_Myptr() Line 2274 C++
ChessUltimate.exe!std::string::operator=(const std::string & _Right) Line 3230 C++
ChessUltimate.exe!ChessBoard::makeMove(int from_number, int from_letter, int to_number, int to_letter) Line 80 C++
ChessUltimate.exe!main() Line 18 C++
相关代码
ChessEngine.h
#pragma once #include <iostream> #include <sstream> using namespace std; class ChessBoard { public: string** board; ChessBoard(string FEN) { // Make a 2D Array board = new string * [8]; // Rows for (int i = 0; i < 8; ++i) { board[i] = new string[8]; // Columns } // FEN parsing logic here int row = 7; int col = 0; for (char c : FEN) { if (isdigit(c)) { col += c - '0'; } else if (c == '/') { row--; col = 0; } else if (c != ' ') { board[row][col] = c; col++; } } } ~ChessBoard() { for (int i = 0; i < 8; ++i) { delete[] board[i]; } delete[] board; } void drawChessBoard() { for (int i = 7; i >= 0; --i) { cout << i + 1 << " "; for (int j = 0; j < 8; ++j) { if (board[i][j].empty()) { if ((i + j) % 2 == 0) cout << "|#"; else cout << "|_"; } else { cout << "|" << board[i][j]; } } cout << "|\n"; } cout << " 1 2 3 4 5 6 7 8\n"; } void makeMove(int from_number, int from_letter, int to_number, int to_letter) { board [to_number-1][to_letter-1] = board[from_number-1][from_letter - 1]; board [from_number-1][from_letter-1] = ""; } };
ChessUltimate.cpp(主文件)
#include <iostream> #include "ChessBoard.h" using namespace std; ChessBoard* board; int main() { board = new ChessBoard("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR"); board->drawChessBoard(); while (true) { string move; cin >> move; board->makeMove(move[1], move[0], move[3], move[2]); board->drawChessBoard(); } delete board; }
问题根源与修复
核心问题
main函数中直接将move的字符值传递给makeMove的整数参数。例如输入字符'1',其ASCII值为49,而非整数1,导致计算后的数组索引为49-1=48,远超出棋盘数组的合法索引范围(0-7),触发内存越界写访问错误。
修复步骤
修正字符到整数的转换
修改main函数中makeMove的调用代码,将字符转换为对应整数:board->makeMove(move[1] - '0', move[0] - '0', move[3] - '0', move[2] - '0');原理:ASCII中数字字符
'0'到'9'是连续的,减去'0'即可得到对应的整数值。添加输入合法性检查(推荐)
避免用户输入非法格式导致错误,在处理移动前添加检查逻辑:while (true) { string move; cin >> move; // 检查输入长度是否为4 if (move.size() != 4) { cout << "输入错误:请输入4位数字(如1144)\n"; continue; } // 检查每个字符是否为1-8的数字 bool valid = true; for (char c : move) { if (!isdigit(c) || c < '1' || c > '8') { valid = false; break; } } if (!valid) { cout << "输入错误:只能输入1-8的数字\n"; continue; } board->makeMove(move[1] - '0', move[0] - '0', move[3] - '0', move[2] - '0'); board->drawChessBoard(); }确认棋盘索引逻辑
原代码中用户输入的行/列号(1-8)转换为数组索引(0-7)的逻辑正确,无需修改。
内容的提问来源于stack exchange,提问作者kai

