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

Ubuntu下自制大小写不敏感grep程序出现Segmentation fault求助

问题描述

在Windows电脑的Ubuntu环境中,用VS Code编写了一个大小写不敏感的自制grep程序,运行时出现Segmentation fault。大小写敏感版本运行正常,怀疑问题和tolower()函数有关。

  • 编译命令:gcc mygrepin.c
  • 运行命令:./a.out test test.txt
  • test.txt内容:

hallo das ist ein Test.
test
test
test
test
test

  • 预期输出:

hallo das ist ein Test.
test
test
test
test
test

程序代码:

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

int main (int argc, char *argv[]) {
    if (argc > 3) {
        printf("Too many arguments. Only use 2: your search string and the file name.");
        return -1;
    }

    FILE * fp = fopen(argv[2], "r");
    if(fp == NULL) {
           perror("Unable to open file!");
           return -1;
       }
    char * buffer = NULL;
    size_t bufsize = 0;
    char * lowerBuffer = malloc(sizeof(strlen(buffer)));

    for (int i = 0; buffer[i] != '\0'; i++) {
        lowerBuffer[i] = tolower(buffer[i]);
    }
    
    printf("tolower: %s", lowerBuffer);

    while (getline(&buffer, &bufsize, fp) != -1) {
        if (strstr(buffer, argv[1]))
        {
            printf("%s", buffer);
        }
                
        //printf("%zd", strlen(buffer));
    }
    
    fclose(fp);
    free(buffer);

    return 0;
}
问题分析与修复

你的代码存在多个严重问题,直接导致了段错误,同时完全没实现大小写不敏感的匹配逻辑:

1. 空指针访问触发段错误

  • buffer初始化为NULL,直接用buffer[i]访问内容属于非法解引用空指针,必然触发段错误。
  • 你在调用getline前就操作buffer,但buffer的内存是getline才会分配的,此时它没有有效内存空间。

2. 内存分配逻辑错误

malloc(sizeof(strlen(buffer)))完全错误:

  • buffer为NULL时,strlen(buffer)属于未定义行为,会直接崩溃;
  • sizeof(strlen(buffer))实际取的是size_t类型的字节数(通常是4或8),而非字符串长度,就算buffer有效,也会分配过小的内存,导致越界写入。

3. 大小写不敏感逻辑缺失

当前代码仅错误处理了空的buffer,实际匹配仍用strstr做大小写敏感查找,完全没实现需求。


修复后的代码

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

// 将字符串转为小写的工具函数
char* str_to_lower(const char* src) {
    if (src == NULL) return NULL;
    size_t len = strlen(src);
    char* lower = malloc(len + 1);
    if (lower == NULL) {
        perror("malloc failed");
        exit(EXIT_FAILURE);
    }
    for (size_t i = 0; i < len; i++) {
        // 转成unsigned char避免tolower处理负数的未定义行为
        lower[i] = tolower((unsigned char)src[i]);
    }
    lower[len] = '\0';
    return lower;
}

int main(int argc, char *argv[]) {
    // 检查参数数量是否正确
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <search-string> <filename>\n", argv[0]);
        return EXIT_FAILURE;
    }

    FILE *fp = fopen(argv[2], "r");
    if (fp == NULL) {
        perror("Unable to open file!");
        return EXIT_FAILURE;
    }

    // 将搜索关键词转为小写,后续匹配统一用小写
    char* lower_search = str_to_lower(argv[1]);

    char *buffer = NULL;
    size_t bufsize = 0;
    ssize_t read_len;

    while ((read_len = getline(&buffer, &bufsize, fp)) != -1) {
        // 将当前行转为小写
        char* lower_line = str_to_lower(buffer);
        // 用小写关键词匹配小写行
        if (strstr(lower_line, lower_search) != NULL) {
            // 输出原行内容
            printf("%s", buffer);
        }
        free(lower_line); // 释放当前行的小写缓冲区
    }

    // 释放所有分配的内存
    free(lower_search);
    free(buffer);
    fclose(fp);

    return EXIT_SUCCESS;
}

关键修改说明

  1. 参数检查:新增argc != 3判断,避免参数不足时访问argv的非法索引。
  2. 小写转换工具函数:封装字符串转小写逻辑,同时处理内存分配和tolower的参数安全问题(转unsigned char)。
  3. 匹配逻辑修正:先把搜索关键词转为小写,每行读取后也转为小写,再用strstr匹配,实现大小写不敏感查找。
  4. 内存管理:每次处理完一行后释放对应的小写缓冲区,避免内存泄漏;所有动态分配的内存最终都被释放。
  5. 错误处理:新增malloc失败的处理,用fprintf(stderr)输出错误信息,符合标准错误输出规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 01:55:34