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

读取多个文本文件(或执行两次)时free()函数出现异常

解决读取多文件时free()异常的问题

看起来你遇到的free()异常大概率和内存管理不当有关,结合你给出的代码片段,我整理了几个核心问题点和对应的修复方案:

1. 野指针问题:prev_line数组未初始化

你定义了char *prev_line[999];但没有初始化,数组里的每个元素都是随机的野指针。当你用strncmp(line, prev_line, ...)时,实际上是在和一个无效的内存地址做比较,这不仅逻辑错误,还可能触发内存访问异常,甚至间接导致后续free时的错误(比如误操作了野指针指向的内存)。

如果prev_line是用来存储之前读取的行,你需要:

  • 初始化数组元素为NULL
  • 存储行时要为每行分配内存(比如用strdup()拷贝line的内容)
  • 不再使用时要逐个释放这些指针

2. getline的内存管理混乱

getline会自动为line分配内存(如果初始为NULL),或者在现有内存不够时扩容。但在多文件循环中重复使用同一个line指针时,要注意:

  • 每次打开新文件前,可以调用free(line); line = NULL; len = 0;重置状态,避免残留上一个文件的内存数据干扰
  • 程序结束后必须调用free(line);释放getline分配的内存,否则会泄漏;但如果重复free同一个已经释放的指针,就会触发异常

3. 未释放a的内存泄漏

每次循环中a = malloc(MAX_NAME_SZ * sizeof(char));,但没有对应的free(a);,虽然这不是free异常的直接原因,但长期运行会导致内存泄漏,而且如果a被重复赋值,之前的内存就永久丢失了。

修正后的核心代码示例

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

#define MAX_NAME_SZ 256

int main(int argc, char *argv[]) {
    char *a;
    char *line = NULL;
    char *prev_line[999];
    size_t len = 0;
    ssize_t read; // 注意getline返回的是ssize_t,不是size_t

    // 初始化prev_line数组为NULL,避免野指针
    for (int k = 0; k < 999; k++) {
        prev_line[k] = NULL;
    }

    if (argc > 1) {
        int i = 1;
        FILE *fp;
        while (i < argc) {
            // 分配a的内存并检查是否成功
            a = malloc(MAX_NAME_SZ * sizeof(char));
            if (a == NULL) {
                perror("malloc failed for a");
                exit(EXIT_FAILURE);
            }
            // 复制文件名到a(示例操作)
            strncpy(a, argv[i], MAX_NAME_SZ - 1);
            a[MAX_NAME_SZ - 1] = '\0'; // 确保字符串安全结束

            fp = fopen(argv[i], "r");
            if (fp == NULL) {
                perror("Failed to open file");
                free(a); // 打开失败也要释放a,避免泄漏
                i++;
                continue;
            }

            // 处理新文件前重置line状态
            free(line);
            line = NULL;
            len = 0;

            int line_idx = 0;
            while ((read = getline(&line, &len, fp)) != -1) {
                // 示例:和前一行的前N个字符比较
                if (line_idx > 0 && prev_line[line_idx - 1] != NULL) {
                    if (strncmp(line, prev_line[line_idx - 1], 10) == 0) {
                        printf("Line %d matches previous line's first 10 chars\n", line_idx);
                    }
                }

                // 释放当前位置旧的存储内容(如果有)
                if (prev_line[line_idx] != NULL) {
                    free(prev_line[line_idx]);
                }
                // 拷贝当前行到prev_line,strdup自动分配内存
                prev_line[line_idx] = strdup(line);
                if (prev_line[line_idx] == NULL) {
                    perror("strdup failed");
                    fclose(fp);
                    free(a);
                    exit(EXIT_FAILURE);
                }

                line_idx++;
                if (line_idx >= 999) break; // 防止数组越界
            }

            // 清理当前文件相关资源
            fclose(fp);
            free(a);
            i++;
        }
    }

    // 释放所有剩余内存
    free(line);
    for (int k = 0; k < 999; k++) {
        if (prev_line[k] != NULL) {
            free(prev_line[k]);
        }
    }

    return EXIT_SUCCESS;
}

额外注意点

  • getline的返回值是ssize_t,不是size_t,因为可能返回-1表示错误,所以要修正read的类型,避免符号判断问题
  • 任何内存分配操作(malloc、strdup等)都要检查返回值是否为NULL,防止后续操作野指针
  • 释放内存时要确保指针有效(不是NULL,也不是已经被释放过的),避免double free或free野指针

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:41:00