无法向结构体数组添加元素,触发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;
问题根源
level->points未分配内存:LevelPoint **points仅声明了二维指针,未分配存储一维指针数组的内存,初始为NULL(指向0地址),赋值时触发写0地址的段错误。- 栈内存复用与失效:
list是栈上的局部数组,所有level->points[j]都指向同一块栈内存,循环结束后栈内存会被回收,后续访问会导致未定义行为。 - 数组越界访问:当
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
相关产品推荐
相关产品推荐

