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

ESP32中C语言读取文件存二维数组,循环内外打印结果不一致

问题描述

在ESP32上通过C语言读取文件,尝试将文件中的字符按行存入二维数组。读取过程中在while循环内打印数组结果符合预期,但循环结束后打印数组出现乱码,仅每行末尾的数值正确,怀疑是内存分配问题,需定位并解决。

输入文件格式

#####B#
##### #
####  #
#### ##
     ##
A######

循环内打印输出

[ 35 ][ 35 ][ 35 ][ 35 ][ 35 ][ 66 ][ 35 ]
[ 35 ][ 35 ][ 35 ][ 35 ][ 35 ][ 32 ][ 35 ]
[ 35 ][ 35 ][ 35 ][ 35 ][ 32 ][ 32 ][ 35 ]
[ 35 ][ 35 ][ 35 ][ 35 ][ 32 ][ 35 ][ 35 ]
[ 32 ][ 32 ][ 32 ][ 32 ][ 32 ][ 35 ][ 35 ]
[ 65 ][ 35 ][ 35 ][ 35 ][ 35 ][ 35 ][ 35 ]

循环外打印输出

[ 1073424916 ][ 1073424916 ][ -1688599997 ][ -961455512 ][ -724372320 ][ -1275106563 ][ 35 ]
[ 1073424916 ][ 1073424916 ][ -582559471 ][ -930149664 ][ 1510548983 ][ 1629549381 ][ 35 ]
[ 1073424916 ][ 1073424916 ][ 479218642 ][ 2091780050 ][ 1271856269 ][ -564334767 ][ 35 ]
[ 1073424916 ][ 1073424916 ][ -1348850970 ][ -972490428 ][ 1253901817 ][ 1424904752 ][ 35 ]
[ 1073424916 ][ 1073424916 ][ 731742849 ][ 1319147750 ][ -1130554592 ][ -2097033641 ][ 35 ]
[ 1073424916 ][ 1073424916 ][ 1671172429 ][ -1512979784 ][ -804137078 ][ -153094939 ][ 35 ]

原代码

static const char* TAG = "Filesystem";
FILE* f = fopen("/storage/test.txt", "r");
if (f == NULL) {
    ESP_LOGE(TAG, "Failed to open file for reading");
    return;
}
int height = 0;
int width = 0;
int currentChar;
int** walls = (int**)malloc((height + 1) * sizeof(int*));
while ((currentChar = fgetc(f)) != EOF) {
    if (currentChar == '\n') {
        width = 0;
        height++;
        printf("\n");
    } else if (currentChar != '\r') {
        walls = (int**)realloc(walls, (height + 1) * sizeof(int*));
        walls[height] = (int*)malloc((width + 1) * sizeof(int));
        walls[height][width] = currentChar;
        printf("%s %d %s", "[", walls[height][width], "]");
        width++;
    }
}
printf("\n");
for (int i = 0; i < 6; i++) {
    for (int j = 0; j < 7; j++) {
        printf("%s %d %s", "[", walls[i][j], "]");
    }
    printf("\n");
}
for (int i = 0; i <= height; i++) {
    free(walls[i]);
}
free(walls);
fclose(f);

问题定位

核心错误是每行内存分配逻辑错误:

  • 读取每个字符时,都对当前行执行malloc((width + 1) * sizeof(int)),这会丢弃当前行之前分配的内存,仅保留本次分配的新内存块。
  • 新内存块中只有当前width位置的字符被赋值,其余位置都是未初始化的垃圾值。
  • 循环内仅打印刚赋值的当前位置,所以结果正确;循环外访问该行其他位置时,读取的是未初始化的垃圾数据,仅最后一个字符(最后一次分配的位置)正确。
  • 同时存在内存泄漏:每次重新malloc当前行时,旧的内存块未被释放。

解决方案

修改内存分配逻辑,对当前行使用realloc进行扩容,而非每次重新malloc,保留之前已读取的字符数据。同时优化行指针的分配时机,避免不必要的realloc操作。

修正后代码

static const char* TAG = "Filesystem";
FILE* f = fopen("/storage/test.txt", "r");
if (f == NULL) {
    ESP_LOGE(TAG, "Failed to open file for reading");
    return;
}
int height = 0;
int width = 0;
int currentChar;
// 记录每行的宽度,避免打印时越界
int* row_widths = NULL;
int** walls = NULL;

// 初始化第一行的指针和宽度记录
walls = (int**)malloc(sizeof(int*));
row_widths = (int*)malloc(sizeof(int));
walls[height] = NULL;
row_widths[height] = 0;

while ((currentChar = fgetc(f)) != EOF) {
    if (currentChar == '\n') {
        // 保存当前行的宽度
        row_widths[height] = width;
        width = 0;
        height++;
        // 为下一行分配指针和宽度记录空间
        walls = (int**)realloc(walls, (height + 1) * sizeof(int*));
        row_widths = (int*)realloc(row_widths, (height + 1) * sizeof(int));
        walls[height] = NULL;
        row_widths[height] = 0;
        printf("\n");
    } else if (currentChar != '\r') {
        // 对当前行的内存进行扩容,新增一个int的空间
        walls[height] = (int*)realloc(walls[height], (width + 1) * sizeof(int));
        walls[height][width] = currentChar;
        printf("[ %d ]", walls[height][width]);
        width++;
    }
}
// 保存最后一行的宽度(如果文件末尾没有换行)
row_widths[height] = width;
printf("\n");

// 打印二维数组,根据每行实际宽度遍历
for (int i = 0; i <= height; i++) {
    for (int j = 0; j < row_widths[i]; j++) {
        printf("[ %d ]", walls[i][j]);
    }
    printf("\n");
}

// 释放内存
free(row_widths);
for (int i = 0; i <= height; i++) {
    free(walls[i]);
}
free(walls);
fclose(f);

关键修改点

  1. 使用realloc对当前行内存进行扩容,保留已读取的字符数据,避免内存丢失和泄漏。
  2. 新增row_widths数组记录每行的实际宽度,打印时按需遍历,避免越界访问。
  3. 仅在换行时扩容行指针数组,减少不必要的内存操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 08:42:03