一个函数,返回指向网格上每个可能的骑士运动的指针的 2D 列表。
一切正常,除了我的空间自由功能在随机位置崩溃:
项目 q1.exe 中 0x00007FFB2CC5C55C (ucrtbased.dll) 处出现未处理的异常:0xC0000005:读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突。
它正在尝试释放非法位置,但该位置是随机的,我不知道是什么原因造成的:
typedef char chessPos[2];
typedef struct _chessPosArray {
unsigned int size;
chessPos *positions;
} chessPosArray;
bool isPosInBoard(chessPos pos);
chessPosArray ***validKnightMoves();
chessPos *KnightMoveFromLocation(int row, int col, unsigned int *lenght);
void printKnightMovesInCur(chessPosArray ***possArr, int row, int col);
void freeCPA(chessPosArray ***possArr);
bool isEmpthy(const void *node);
chessPosArray ***validKnightMoves() {
chessPosArray ***finle = (chessPosArray ***)malloc(sizeof(chessPosArray **) * B_SIZE);
if (isEmpthy(finle)) {
printf("Memory allocation failed for final\n");
exit(1);
}
for (int i = 0; i < B_SIZE; i++) {
finle[i] = (chessPosArray **)malloc(sizeof(chessPosArray *) * B_SIZE);
if (isEmpthy(finle[i])) {
printf("Memory allocation failed for final[%d]\n", i);
exit(1);
}
for (int j = 0; j < B_SIZE; j++) {
finle[i][j] = (chessPosArray *)malloc(sizeof(chessPosArray));
if (isEmpthy(finle[i][j])) {
printf("Memory allocation failed for final[%d][%d]\n", i, j);
exit(1);
}
finle[i][j]->positions = KnightMoveFromLocation(i, j, &finle[i][j]->size);
}
}
return finle;
}
chessPos *KnightMoveFromLocation(int row, int col, unsigned int *lenght) {
int columns[8] = { 1, 2, 2, 1, -1, -2, -2, -1 };
int Rows[8] = { -2, -1, 1, 2, 2, 1, -1, -2 };
chessPos posHold;
posHold[0] = 'A' + row;
posHold[1] = '1' + col;
int newlenght = 0;
chessPos *rePos = (chessPos *)malloc(sizeof(chessPos) * 8);
if (isEmpthy(rePos)) {
printf("Memory allocation failed for rePos\n");
exit(1);
}
chessPos *pointer = rePos;
for (int i = 0; i < 8; i++)
{
chessPos posChecker = { posHold[0] + Rows[i], posHold[1] = posHold[1] + columns[i] };
if (isPosInBoard(posChecker)) {
(*pointer)[0] = posChecker[0];
(*pointer)[1] = posChecker[1];
pointer++;
newlenght++;
}
}
realloc(rePos, sizeof(chessPos) * newlenght);
*lenght = newlenght;
return rePos;
}
bool isPosInBoard(chessPos pos) {
int row = pos[0] - 'A';
int col = pos[1] - '1';
if (row < 0 || row >= B_SIZE || col < 0 || col >= B_SIZE) {
return false;
}
return true;
}
void freeCPA(chessPosArray ***possArr) {
for (int i = 0; i < B_SIZE; i++) {
for (int j = 0; j < B_SIZE; j++) {
// vvv this is where the program crashes vvv
free(possArr[i][j]->positions);
free(possArr[i][j]);
}
free(possArr[i]);
}
free(possArr);
}
bool isEmpthy(const void *node) {
if (node == NULL)
return true;
return false;
}
我标记了有问题的行。尝试检查之前是否为空或接下来将其变为空。它穿过孔网格,因此
i
不会出界。
调试位置(每个位置)。 打印它们打印失败的地方,检查空值,使其空。
存在多个问题。主要:
realloc(rePos, sizeof(chessPos) * newlenght)
也可能返回与 rePos
不同的指针。 在这种情况下,在调用 rePos
之后使用 realloc
具有未定义的行为,这可能解释了将其传递给 free
时发生的崩溃。返回值应存储在 rePos
中,但前提是非 NULL。
此外,您还应该检查分配失败并在这种情况下保留原始指针。 重新分配该块对于您的目的来说似乎有点过分,只需删除此行即可。isEmpthy
应拼写为 isEmpty
或重命名为 isNull
并简化为
bool isNull(const void *node) { return node == NULL; }
在 C 语言中使用函数来实现此目的并不惯用,只需编写:
if (!rePos) {
fprintf(stderr, "Memory allocation failed for rePos\n");
exit(1);
}
chessPos posChecker = { posHold[0] + Rows[i], posHold[1] = posHold[1] + columns[i] };
中的初始化程序不正确,您不应该更新posHold[i]
。 使用这个代替:
chessPos posChecker = { posHold[0] + Rows[i], posHold[1] + columns[i] };
请注意,不需要如此多的间接寻址,并且使用超过 2 个间接寻址是数据结构过于复杂的好兆头:您应该使用
chessPosArray
结构的 2D 数组定义单个结构,并在单个调用中分配并填充两个简单的嵌套循环:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#define B_SIZE 8
typedef char chessPos[2];
typedef struct chessPosArray {
unsigned int size;
chessPos positions[8]; // up to 8 possible destinations
} chessPosArray;
typedef struct chessKnightMoves {
chessPosArray finle[B_SIZE][B_SIZE];
};
bool isPosInBoard(chessPos pos);
chessKnightMoves *validKnightMoves(void);
unsigned int knightMoveFromLocation(chessPos *rePos, int row, int col);
void printKnightMovesInCur(chessKnightMoves *kp, int row, int col);
void freeCPA(chessKnightMoves *kp);
chessKnightMoves *validKnightMoves(void) {
// calloc initializes the memory block to all bits 0.
chessKnightMoves *kp = calloc(1, sizeof(*kp));
if (!kp) {
fprintf(stderr, "Memory allocation failed for knithMoves\n");
exit(1);
}
for (int i = 0; i < B_SIZE; i++) {
for (int j = 0; j < B_SIZE; j++) {
kp->finle[i][j].size = KnightMoveFromLocation(finle[i][j].positions, i, j);
}
}
return kp;
}
unsigned int knightMoveFromLocation(chessPos *rePos, int row, int col) {
static int const cols[8] = { 1, 2, 2, 1, -1, -2, -2, -1 };
static int const rows[8] = { -2, -1, 1, 2, 2, 1, -1, -2 };
unsigned int count = 0;
for (int i = 0; i < 8; i++) {
chessPos posChecker = { 'A' + row + rows[i], '1' + col + cols[i] };
if (isPosInBoard(posChecker)) {
rePos[count] = posChecker;
count++;
}
}
return count;
}
bool isPosInBoard(chessPos pos) {
int row = pos[0] - 'A';
int col = pos[1] - '1';
return (row >= 0 && row < B_SIZE && col >= 0 && col < B_SIZE);
}
void freeCPA(chessKnightMoves *kp) {
free(kp);
}