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; }
关键修改说明
- 参数检查:新增
argc != 3判断,避免参数不足时访问argv的非法索引。 - 小写转换工具函数:封装字符串转小写逻辑,同时处理内存分配和
tolower的参数安全问题(转unsigned char)。 - 匹配逻辑修正:先把搜索关键词转为小写,每行读取后也转为小写,再用
strstr匹配,实现大小写不敏感查找。 - 内存管理:每次处理完一行后释放对应的小写缓冲区,避免内存泄漏;所有动态分配的内存最终都被释放。
- 错误处理:新增
malloc失败的处理,用fprintf(stderr)输出错误信息,符合标准错误输出规范。
内容的提问来源于stack exchange,提问作者learning
相关产品推荐
相关产品推荐

