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

模拟grep -f命令的C程序出现Segmentation fault (core dumped)问题求助

问题排查与代码优化(模拟grep -f功能)

一、段错误原因分析

  • 文件打开逻辑错误:原代码中fopen("aux1","r")使用字符串字面量而非存储文件名的变量,导致尝试打开名为aux1的不存在文件,返回的file1/file2为空指针,后续fscanf操作空指针触发段错误。
  • 未做参数合法性检查:直接访问argv[1]和argv[2],若运行时传入参数不足2个(argc < 3),会访问非法内存地址触发段错误。
  • 缓冲区溢出风险:s1/s2仅分配100字节,若文件内容超过该长度,strcat会越界写入,破坏内存结构引发段错误。
  • 空指针解引用:strstr未找到匹配时返回NULL,直接用printf("%s", NULL)会触发段错误。
  • 核心逻辑偏差:原代码将两个文件内容拼接成单一字符串后查找匹配,完全不符合grep -f的实际逻辑——grep -f是用第一个文件的每一行作为匹配模式,在第二个文件的每一行中查找匹配,输出所有包含任意模式的行。

二、优化方案与修正代码

优化点说明

  • 移除冗余的aux1/aux2变量,直接用argv[1]、argv[2]作为文件名打开文件。
  • 增加参数检查:参数不足时向stderr输出错误提示并退出。
  • 增加文件打开校验:文件打开失败时向stderr输出错误信息并清理资源。
  • 采用逐行处理逻辑,贴合grep -f的实际功能。
  • 使用足够大的缓冲区避免溢出,同时处理换行符。

修正后的代码

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

#define BUF_SIZE 1024

int main(int argc, char *argv[]) {
    // 检查参数数量是否足够
    if (argc < 3) {
        fprintf(stderr, "用法: %s <模式文件> <目标文件>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    // 打开模式文件
    FILE *pattern_file = fopen(argv[1], "r");
    if (!pattern_file) {
        fprintf(stderr, "无法打开模式文件: %s\n", argv[1]);
        exit(EXIT_FAILURE);
    }

    // 打开目标文件
    FILE *target_file = fopen(argv[2], "r");
    if (!target_file) {
        fprintf(stderr, "无法打开目标文件: %s\n", argv[2]);
        fclose(pattern_file);
        exit(EXIT_FAILURE);
    }

    char pattern[BUF_SIZE];
    char line[BUF_SIZE];
    // 遍历每个模式行
    while (fgets(pattern, BUF_SIZE, pattern_file) != NULL) {
        // 移除模式行末尾的换行符
        size_t len = strlen(pattern);
        if (len > 0 && pattern[len-1] == '\n') {
            pattern[len-1] = '\0';
        }
        // 跳过空模式行
        if (strlen(pattern) == 0) {
            continue;
        }

        // 将目标文件指针重置到开头,匹配当前模式
        rewind(target_file);
        // 遍历目标文件的每一行
        while (fgets(line, BUF_SIZE, target_file) != NULL) {
            // 检查当前行是否包含模式
            if (strstr(line, pattern) != NULL) {
                // 输出匹配的行(保留原换行符)
                fputs(line, stdout);
            }
        }
    }

    // 关闭文件资源
    fclose(pattern_file);
    fclose(target_file);

    return 0;
}

三、代码说明

  • 错误输出规范:使用fprintf(stderr, ...)向标准错误流输出提示,符合Unix工具的错误输出习惯,exit(EXIT_FAILURE)返回非0状态码标识运行失败。
  • 资源安全:文件打开失败时会关闭已打开的其他文件,避免资源泄漏。
  • 逻辑贴合:完全复刻grep -f的逐模式、逐行匹配逻辑,输出符合预期的结果。
  • 缓冲区安全:定义BUF_SIZE为1024,足够处理大多数文本行,fgets会自动截断过长内容,避免缓冲区溢出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 07:27:36