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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 22:42:49