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

如何用系统调用在C语言中读取文件每行并存储至内存?求助排查问题

问题分析与修正方案

你的代码存在的核心问题

  • 指针指向重复且栈内存不安全:temp是栈上分配的数组,你把files[j] = temp,所有数组元素的指针都会指向同一块栈内存。后续循环修改temp时,之前存入的内容会被覆盖,程序退出当前函数后,栈内存释放,这些指针会变成野指针,访问会导致未定义行为。
  • 缺少字符串结束符:C语言字符串必须以\0结尾,你的代码在存入temp后没有添加这个结束符,后续使用这些字符串(比如打印)会读取到内存中的垃圾数据。
  • 未处理无换行的最后一行:如果文件最后一行没有以\n结尾,循环结束后这部分内容不会被存入数组。
  • 缓冲区溢出风险:temp固定长度100,若某一行超过99个字符(留一个位置给\0),会导致缓冲区溢出,破坏栈上其他数据。
  • 未处理文件打开失败:open可能返回-1(比如文件不存在),直接使用fd会出错。

修正后的代码示例

我们可以用动态分配内存来解决指针指向问题,同时修复其他缺陷:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "用法: %s <文件名>\n", argv[0]);
        exit(1);
    }

    char *files[100]; // 最多存100行
    char buffer;
    int i = 0, j = 0;
    // 初始分配一块小内存,后续按需扩容
    char *temp = malloc(100 * sizeof(char));
    if (!temp) {
        perror("malloc失败");
        exit(1);
    }
    size_t temp_capacity = 100;

    int fd = open(argv[1], O_RDONLY);
    if (fd == -1) {
        perror("打开文件失败");
        free(temp);
        exit(1);
    }

    while (read(fd, &buffer, 1) > 0) {
        if (buffer != '\n') {
            // 检查缓冲区是否已满,满了就扩容
            if (i >= temp_capacity - 1) {
                temp_capacity *= 2;
                char *new_temp = realloc(temp, temp_capacity * sizeof(char));
                if (!new_temp) {
                    perror("realloc失败");
                    free(temp);
                    close(fd);
                    exit(1);
                }
                temp = new_temp;
            }
            temp[i++] = buffer;
        } else {
            // 添加字符串结束符
            temp[i] = '\0';
            // 为当前行分配独立内存,拷贝temp内容
            files[j] = malloc(strlen(temp) + 1);
            if (!files[j]) {
                perror("malloc失败");
                // 释放已分配的内存
                for (int k = 0; k < j; k++) {
                    free(files[k]);
                }
                free(temp);
                close(fd);
                exit(1);
            }
            strcpy(files[j], temp);
            j++;
            if (j >= 100) {
                fprintf(stderr, "超过最大行数限制100\n");
                break;
            }
            i = 0;
        }
    }

    // 处理最后一行没有换行的情况
    if (i > 0) {
        temp[i] = '\0';
        files[j] = malloc(strlen(temp) + 1);
        if (!files[j]) {
            perror("malloc失败");
            for (int k = 0; k < j; k++) {
                free(files[k]);
            }
            free(temp);
            close(fd);
            exit(1);
        }
        strcpy(files[j], temp);
        j++;
    }

    // 示例:打印所有读取到的行
    printf("读取到%d行内容:\n", j);
    for (int k = 0; k < j; k++) {
        printf("%s\n", files[k]);
    }

    // 释放所有分配的内存
    for (int k = 0; k < j; k++) {
        free(files[k]);
    }
    free(temp);
    close(fd);

    return 0;
}

关键改进点

  • 动态分配独立内存:每行内容都用malloc分配独立的内存块,避免所有指针指向同一块栈内存的问题。
  • 缓冲区自动扩容:通过realloc动态调整临时缓冲区大小,避免固定长度导致的溢出。
  • 添加字符串结束符:确保每个存储的字符串都是合法的C语言字符串。
  • 处理边界情况:包括文件打开失败、最后一行无换行、超过最大行数限制等。
  • 内存泄漏防护:在出错时释放已分配的内存,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 23:45:34