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

无法向结构体数组添加元素,触发Segmentation Fault错误求助

内存访问错误(SEGV)排查:LevelPoint二维数组赋值问题

相关代码定义

结构体定义

typedef struct LevelPoint {
    Material ground_material;
    int ground_height;
} LevelPoint;

数组与指针声明

struct LevelPoint list[30];
LevelPoint **points; // 对应level->points

赋值循环代码

for(int j =0;j<level->width;j++){
        for(int i = 0;i< level->height;i++){
            //bitsOmzetter返回0-3的数值
            k = bitsOmzetter(&l,ptr,&w);
            if(k == 3){
                if(i==0){
                    list[i] = level->points[j-1][level->height-1];
                }else{
                    list[i] = list[i-1];
                }
            }else{
                LevelPoint point;
                point.ground_material = k;
                point.ground_height = bitsOmzetter(&l,ptr,&w)+1;;
                list[i] = point;
            }
        } 
        level->points[j] = list;
    }

错误信息

==12788==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x559c5edaa671 bp 0x7ffda2a59db0 sp 0x7ffda2a57ce0 T0)
==12788==The signal is caused by a WRITE memory access.
==12788==Hint: address points to the zero page.
    #0 0x559c5edaa671 in levelloader_load_binary_level /home/student/Desktop/Systeemprogrammeren2022-project-groep-22/game/level/c_levelloader.c:66

第66行代码为:level->points[j] = list;

问题根源

  1. level->points未分配内存:LevelPoint **points仅声明了二维指针,未分配存储一维指针数组的内存,初始为NULL(指向0地址),赋值时触发写0地址的段错误。
  2. 栈内存复用与失效:list是栈上的局部数组,所有level->points[j]都指向同一块栈内存,循环结束后栈内存会被回收,后续访问会导致未定义行为。
  3. 数组越界访问:当j=0时,访问level->points[j-1]即level->points[-1],属于越界访问,会触发未定义行为。

修复方案

步骤1:为二维指针分配一维内存

在循环前先为level->points分配存储每行指针的内存:

// 为level->points分配一维指针数组内存
level->points = malloc(level->width * sizeof(LevelPoint*));
if (!level->points) {
    // 处理内存分配失败,比如打印错误后退出
    perror("malloc failed for level->points");
    return -1;
}

步骤2:为每行分配独立的堆内存

去掉栈数组list,每次循环为当前行分配独立的堆内存,避免复用和失效问题:

for(int j =0;j<level->width;j++){
    // 为当前行分配LevelPoint数组内存
    LevelPoint* current_row = malloc(level->height * sizeof(LevelPoint));
    if (!current_row) {
        perror("malloc failed for current_row");
        // 释放已分配的内存,避免内存泄漏
        for (int k = 0; k < j; k++) {
            free(level->points[k]);
        }
        free(level->points);
        return -1;
    }

    for(int i = 0;i< level->height;i++){
        k = bitsOmzetter(&l,ptr,&w);
        if(k == 3){
            if(i==0){
                // 处理j=0的边界情况,避免越界访问
                if (j == 0) {
                    // 根据业务需求设置默认值,示例用0填充
                    current_row[i].ground_material = 0;
                    current_row[i].ground_height = 0;
                } else {
                    current_row[i] = level->points[j-1][level->height-1];
                }
            }else{
                current_row[i] = current_row[i-1];
            }
        }else{
            current_row[i].ground_material = k;
            current_row[i].ground_height = bitsOmzetter(&l,ptr,&w)+1;
        }
    } 
    level->points[j] = current_row;
}

步骤3:内存释放(必要时)

使用完level->points后,要依次释放每行内存和一维指针数组内存,避免内存泄漏:

for (int j = 0; j < level->width; j++) {
    free(level->points[j]);
}
free(level->points);
level->points = NULL; // 避免野指针

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 16:10:32