使用char**存储地图触发段错误,请求代码问题排查
段错误问题分析与修复
问题背景
需要编写函数遍历存储在char **中的地图,检查每个字符周围8个位置(共9个)中至少有2个'#',使用matrix_t结构体实现检查逻辑。仅允许使用指定函数/系统调用,但程序出现段错误,Valgrind显示错误触发在set_mat_nbr的if语句中。
相关代码如下:
create_matrix函数
matrix_t *create_matrix(char **map, size_t y, size_t x) { matrix_t *out = malloc(sizeof(matrix_t)); if (!out) { my_perr("[ERROR] Memory's allocation failure\n"); } out->nbr = 0; set_mat_nbr(out, map, y - 1, x); set_mat_nbr(out, map, y, x); set_mat_nbr(out, map, y + 1, x); return out; }
set_mat_nbr函数
void set_mat_nbr(matrix_t *matrix, char **map, long y, long x) { if (y != 0 && map[y] != NULL && x != 0 && map[y][x - 1] == '#') { matrix->nbr++; } if (y != 0 && map[y] != NULL && map[y][x] == '#') { matrix->nbr++; } if (y != 0 && map[y] != NULL && map[y][x + 1] == '#') { matrix->nbr++; } }
调用函数check_border
void check_border(char **map) { size_t y = 0, x = 0; matrix_t *matrix = NULL; while (map[0][x] != '\0') { matrix = create_matrix(map, 0, x); if (matrix->nbr < 2) { my_perr("[ERROR] Corrupted border\n"); } free(matrix); x++; } }
问题分析与修复
1. 无符号整数溢出导致非法索引
create_matrix的y参数是size_t(无符号整数),当调用create_matrix(map, 0, x)时,y - 1会因无符号溢出变成极大值(如SIZE_MAX),访问map[y-1]必然越界触发段错误。
修复:
添加边界判断避免溢出,同时确认y+1对应的行存在:
matrix_t *create_matrix(char **map, size_t y, size_t x) { matrix_t *out = malloc(sizeof(matrix_t)); if (!out) { my_perr("[ERROR] Memory's allocation failure\n"); exit(EXIT_FAILURE); // 内存分配失败后终止程序,避免空指针访问 } out->nbr = 0; // 仅当y>0时处理y-1行 if (y > 0) { set_mat_nbr(out, map, (long)y - 1, x); } set_mat_nbr(out, map, (long)y, x); // 确认y+1行存在再处理 if (map[y+1] != NULL) { set_mat_nbr(out, map, (long)y + 1, x); } return out; }
2. set_mat_nbr边界检查逻辑错误
- 多余的
y != 0判断:导致y=0的行完全不被处理,与检查顶部边界的需求矛盾。 - 缺少
x+1越界检查:访问map[y][x+1]时未确认是否超出字符串长度,可能访问非法内存。 - 检查顺序虽无错误,但逻辑覆盖不全。
修复:
移除不必要的判断,补充x方向的边界检查:
void set_mat_nbr(matrix_t *matrix, char **map, long y, size_t x) { if (map[y] == NULL) { return; } // 检查x-1:仅x>0时访问 if (x > 0 && map[y][x - 1] == '#') { matrix->nbr++; } // 检查当前x位置 if (map[y][x] == '#') { matrix->nbr++; } // 检查x+1:确认未到字符串末尾 if (map[y][x + 1] != '\0' && map[y][x + 1] == '#') { matrix->nbr++; } }
3. 内存分配失败后未终止程序
create_matrix中malloc失败时仅打印错误,后续访问out->nbr会因空指针触发段错误。
修复:
在malloc失败后调用exit(EXIT_FAILURE)终止程序,如上述修复代码所示。
4. check_border未确认map合法性
若map为空指针或map[0]为NULL,map[0][x]会直接触发段错误。
修复:
添加初始合法性检查:
void check_border(char **map) { if (map == NULL || map[0] == NULL) { my_perr("[ERROR] Invalid map\n"); return; } size_t y = 0, x = 0; matrix_t *matrix = NULL; while (map[0][x] != '\0') { matrix = create_matrix(map, 0, x); if (matrix->nbr < 2) { my_perr("[ERROR] Corrupted border\n"); } free(matrix); x++; } }
内容的提问来源于stack exchange,提问作者user20854333
相关产品推荐
相关产品推荐

