char二级指针的内存分配与赋值问题求助
解决char**地图加载的内存泄漏问题
核心思路
放弃固定大小的内存分配,改为先读取文件头获取实际尺寸,再按需分配内存,同时严格处理文件读取流程,避免内存泄漏。
分步实现
1. 读取地图尺寸
打开文件后,先解析首行的宽(列数)和高(行数)——这两个值决定了后续需要分配的内存大小:
int cols, rows; // 假设首行格式为 "宽度 高度" if (fscanf(fp, "%d %d", &cols, &rows) != 2) { fclose(fp); return NULL; // 格式错误直接返回 }
2. 跳过玩家位置行
读取并丢弃第二行的玩家位置数据,注意处理换行符避免影响后续读取:
char skip_buf[256]; // 跳过首行剩余的换行符 while (fgetc(fp) != '\n' && !feof(fp)); // 读取第二行并丢弃 if (fgets(skip_buf, sizeof(skip_buf), fp) == NULL) { fclose(fp); return NULL; }
3. 按需分配二级指针内存
- 先分配存储行指针的数组,大小为地图行数:
char** map = (char**)malloc(sizeof(char*) * rows); if (!map) { fclose(fp); return NULL; } // 分配失败直接返回 - 逐行分配每行的字符空间(需额外+1存储字符串结束符
\0),并读取地图内容:for (int i = 0; i < rows; i++) { map[i] = (char*)malloc(sizeof(char) * (cols + 1)); if (!map[i]) { // 分配失败时,必须释放已分配的所有内存 for (int j = 0; j < i; j++) free(map[j]); free(map); fclose(fp); return NULL; } // 读取一行地图内容(假设每行无空格,长度等于cols) fscanf(fp, "%s", map[i]); // 安全处理:手动截断确保长度符合要求 map[i][cols] = '\0'; }
4. 内存泄漏预防要点
- 每次
malloc后必须检查返回值,避免空指针操作 - 中途出错时,要逐层释放已分配的内存(先释放每行,再释放行指针数组)
- 使用完地图后,要按以下方式释放内存:
void freeMap(char** map, int rows) { for (int i = 0; i < rows; i++) free(map[i]); free(map); }
完整符合要求的代码示例
假设给定的函数签名为char** loadMap(const char* filename):
#include <stdio.h> #include <stdlib.h> #include <string.h> char** loadMap(const char* filename) { FILE* fp = fopen(filename, "r"); if (!fp) return NULL; int cols, rows; if (fscanf(fp, "%d %d", &cols, &rows) != 2) { fclose(fp); return NULL; } // 跳过玩家位置行 char skip_buf[256]; while (fgetc(fp) != '\n' && !feof(fp)); if (fgets(skip_buf, sizeof(skip_buf), fp) == NULL) { fclose(fp); return NULL; } // 分配行指针数组 char** map = (char**)malloc(sizeof(char*) * rows); if (!map) { fclose(fp); return NULL; } // 逐行读取地图 for (int i = 0; i < rows; i++) { map[i] = (char*)malloc(sizeof(char) * (cols + 1)); if (!map[i]) { // 回滚释放已分配内存 for (int j = 0; j < i; j++) free(map[j]); free(map); fclose(fp); return NULL; } if (fscanf(fp, "%s", map[i]) != 1) { // 读取失败,回滚释放 for (int j = 0; j <= i; j++) free(map[j]); free(map); fclose(fp); return NULL; } map[i][cols] = '\0'; // 确保字符串终止 } fclose(fp); return map; } // 配套的内存释放函数(需调用者自行使用) void freeMap(char** map, int rows) { for (int i = 0; i < rows; i++) { free(map[i]); } free(map); }
内容的提问来源于stack exchange,提问作者TechnoCheese
相关产品推荐
相关产品推荐

