C语言文本编辑器运行触发Segmentation Fault错误原因排查
C语言文本编辑器执行触发Segmentation Fault的成因分析
问题现象
编译无报错,但执行时无论是创建新文件还是打开现有.txt文件,终端均报错:
./a.out Enter the filename: hello Enter the start line number: 1 Enter the end line number: 9 Segmentation fault (core dumped)
触发错误的代码
#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX_LINE_LENGTH 1024 void edit_lines(char* buffer, int start_line, int end_line) { char* start = buffer; // Move the start pointer to the start_line position for (int i = 0; i < start_line - 1; i++) { start = strchr(start, '\n'); if (start == NULL) { printf("Error: Invalid line number\n"); return; } start++; } char* end = start; // Move the end pointer to the end_line position for (int i = start_line; i < end_line; i++) { end = strchr(end, '\n'); if (end == NULL) { printf("Error: Invalid line number\n"); return; } end++; } char* line_end = strchr(end, '\n'); if (line_end) { *line_end = '\0'; char saved[MAX_LINE_LENGTH] = {0}; strncpy(saved, line_end + 1, sizeof(saved) - 1); saved[sizeof(saved) - 1] = '\0'; char new_lines[MAX_LINE_LENGTH]; printf("Enter the new lines (press Enter twice to finish):\n"); fgets(new_lines, sizeof(new_lines), stdin); char* nl_pos = strchr(new_lines, '\n'); while (nl_pos) { *nl_pos = '\0'; strcat(start, new_lines); strcat(start, "\n"); fgets(new_lines, sizeof(new_lines), stdin); nl_pos = strchr(new_lines, '\n'); } strcat(start, saved); } else { printf("Error: Invalid line number\n"); } } int main(int argc, char** argv) { char* buffer = NULL; FILE* f; char filename[1024] = {0}; if (argc < 2) { // Create a new file printf("Enter the filename: "); fgets(filename, sizeof(filename), stdin); filename[strcspn(filename, "\n")] = '\0'; f = fopen(filename, "w"); if (!f) { printf("Error creating file %s\n", filename); return 1; } } else { // Open an existing file f = fopen(argv[1], "r"); if (!f) { printf("Error opening file %s\n", argv[1]); return 1; } // Get the size of the file if (fseek(f, 0, SEEK_END) != 0) { printf("Error seeking end of file %s\n", argv[1]); fclose(f); return 1; } long file_size = ftell(f); rewind(f); // Allocate memory for the buffer buffer = (char*)malloc(file_size + 1); if (buffer == NULL) { printf("Error allocating memory\n"); fclose(f); return 1; } // Read the file contents into the buffer if (fread(buffer, 1, file_size, f) != file_size) { printf("Error reading file %s\n", argv[1]); free(buffer); fclose(f); return 1; } buffer[file_size] = '\0'; fclose(f); } int start_line = 0, end_line = 0; printf("Enter the start line number: "); scanf("%d", &start_line); printf("Enter the end line number: "); scanf("%d", &end_line); edit_lines(buffer, start_line, end_line); f = fopen(argc < 2 ? filename : argv[1], "w"); if (!f) { printf("Error opening file %s for writing\n", argc < 2 ? filename : argv[1]); free(buffer); return 1; } if (fwrite(buffer, strlen(buffer), 1, f) != 1) { printf("Error writing to file %s\n", argc < 2 ? filename : argv[1]); free(buffer); fclose(f); return 1; } free(buffer); fclose(f); return 0; }
错误成因分析
- 新文件场景下buffer为空指针:当通过交互创建新文件时(
argc<2分支),代码仅创建文件,但buffer始终保持NULL状态。调用edit_lines(buffer, ...)时,函数直接对NULL指针执行strchr操作,直接触发段错误。 - 内存越界写入:即使是打开已有文件的场景,
malloc分配的内存仅为原文件尺寸+1。后续用strcat往buffer追加新内容时,未检查内存是否足够,新内容超出分配的内存范围会破坏堆结构,最终触发段错误。 - 输入缓冲区残留换行符:
scanf读取行号后,输入缓冲区会残留换行符,后续fgets会直接读到空行,引发逻辑异常,间接增加出错概率。 - 无效行号处理不彻底:当用户输入的
end_line超过文件实际行数时,strchr返回NULL,函数打印错误后返回,但主函数后续依然会对buffer执行写入操作,若此时buffer状态异常(比如新文件场景下还是NULL),就会触发段错误。
内容的提问来源于stack exchange,提问作者Karma
相关产品推荐
相关产品推荐

