You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言实现国际象棋骑士合法移动数组程序崩溃求助

骑士合法移动函数的错误分析与修复

核心崩溃原因:空指针解引用

在validKnightMoves函数中,你仅分配了三维数组的前两层(chessPosArray***和chessPosArray**),但每个arr[i][j](chessPosArray*类型指针)并未指向有效的chessPosArray结构体。直接在checkKnightMoves中使用arrptr[row][col]->positions会触发空指针解引用,这是程序崩溃(退出码-1073741819)的根本原因。

其他关键问题

  • 坐标范围判断错误:代码中row/col是0-based索引(0-7对应棋盘8行8列),但你用newx > 0 && newx <=8的条件,会错误排除0索引对应的合法位置(如棋盘第1行)。正确范围应为newx >=0 && newx <8、newy >=0 && newy <8。
  • 内存分配逻辑错误:
    • realloc返回值未保存:realloc可能返回新内存地址,直接调用不赋值会导致内存泄漏或访问失效内存。
    • 扩容条件错误:counter > physicalsize会导致扩容不及时,应改为counter >= physicalsize(当元素数等于物理容量时扩容)。
  • 缓冲区溢出风险:chessPos定义为char[2],但sprintf写入两个字符时会自动添加终止符'\0',超出数组容量。直接赋值字符更安全。
  • 内存大小计算不准确:第一层和第二层分配时,未明确指向指针的大小,需修正为对应指针类型的大小。

修正后的代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

// 改为char[3]以容纳字符串终止符,避免溢出
typedef char chessPos[3];

typedef struct _chessPosArray 
{
    unsigned int size;
    chessPos* positions;
} chessPosArray;

chessPosArray*** validKnightMoves();
void checkKnightMoves(chessPosArray*** arrptr, int row, int col);

int main() 
{
    chessPosArray ***arr = validKnightMoves();

    // 0-based索引中,第3行第3列对应arr[2][2]
    printf("%d\n", arr[2][2]->size);

    // 释放内存,避免泄漏
    for(int i=0; i<8; i++){
        for(int j=0; j<8; j++){
            free(arr[i][j]->positions);
            free(arr[i][j]);
        }
        free(arr[i]);
    }
    free(arr);

    return 0;
}

chessPosArray*** validKnightMoves() 
{
    // 分配第一层:8个指向指针数组的指针
    chessPosArray*** arr = malloc(sizeof(chessPosArray**) * 8);
    if (arr == NULL)
    {
        printf("allocation failure");
        exit(1);
    }

    for(int i = 0; i < 8; i++) 
    {
        // 分配第二层:每行对应8个指向结构体的指针
        arr[i] = malloc(sizeof(chessPosArray*) * 8);
        if (arr[i] == NULL)
        {
            printf("allocation failure");
            exit(1);
        }
    }
    
    for (int i = 0; i < 8; i++) 
    {
        for(int j = 0; j < 8; j++) 
        {
            checkKnightMoves(arr, i, j);
        }
    }
    
    return arr;
}

void checkKnightMoves (chessPosArray *** arrptr, int row, int col) 
{
    int newx, newy;
    int counter = 0;
    int physicalsize = 1;

    int dx[8] = { 2, 2, 1, 1, -1, -1, -2, -2 };
    int dy[8] = { 1, -1, 2, -2, 2, -2, 1, -1 };
    
    // 先分配chessPosArray结构体本身
    arrptr[row][col] = malloc(sizeof(chessPosArray));
    if (arrptr[row][col] == NULL)
    {
        printf("allocation failure");
        exit(1);
    }

    // 分配初始的positions数组
    arrptr[row][col]->positions = malloc(sizeof(chessPos) * physicalsize);
    if (arrptr[row][col]->positions == NULL)
    {
        printf("allocation failure");
        exit(1);
    }

    for(int i = 0; i < 8; i++) 
    {
        newx = row + dx[i];
        newy = col + dy[i];

        // 正确的0-based范围判断
        if(newx >= 0 && newy >= 0 && newx < 8 && newy < 8) 
        {
            if(counter >= physicalsize) 
            {
                // 保存realloc返回的新地址
                chessPos* temp = realloc(arrptr[row][col]->positions, sizeof(chessPos) * physicalsize * 2);
                if (temp == NULL)
                {
                    printf("reallocation failure");
                    exit(1);
                }
                arrptr[row][col]->positions = temp;
                physicalsize *= 2;
            }
            
            // 直接赋值字符,避免缓冲区溢出
            arrptr[row][col]->positions[counter][0] = 'A' + newx;
            arrptr[row][col]->positions[counter][1] = '1' + newy;
            arrptr[row][col]->positions[counter][2] = '\0'; // 添加字符串终止符
            counter++;
        }
    }

    arrptr[row][col]->size = counter;
}

修正说明

  1. 新增chessPosArray结构体的内存分配,解决空指针解引用问题。
  2. 修正坐标范围判断,适配0-based索引逻辑。
  3. 修复realloc使用方式,保存返回的新内存地址。
  4. 改为直接赋值字符,消除缓冲区溢出风险。
  5. 添加内存释放逻辑,避免内存泄漏。
  6. 主函数中调整索引为arr[2][2],对应0-based的第3行第3列。

内容的提问来源于stack exchange,提问作者astralvampx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 12:17:11