在c中:我的特殊免费功能拒绝工作

问题描述 投票:0回答:1

一个函数,返回指向网格上每个可能的骑士运动的指针的 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
不会出界。

调试位置(每个位置)。 打印它们打印失败的地方,检查空值,使其空。

c pointers malloc free chess
1个回答
0
投票

存在多个问题。主要:

    即使重新分配的大小小于当前大小,
  • 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);
}
© www.soinside.com 2019 - 2024. All rights reserved.