C语言qsort排序160万行单词文本时数组超限致段错误的解决求助
解决大数量字符串排序的动态内存分配问题
你的代码触发段错误的核心原因是静态数组char *line_array[1000001]分配在栈内存中,而栈的可用空间通常仅有几MB,当数组元素数量超过栈的承载上限时,就会引发栈溢出导致段错误。改用malloc在堆内存中分配动态数组即可解决该问题——堆内存的可用空间远大于栈,足以容纳160万甚至更多的字符串指针。
修改后的完整代码
#include <stdio.h> #include <string.h> #include <stdlib.h> static void sort_a(void *array, size_t n); static int cmpr(const void *a, const void *b); int main(void) { static const char filename[] = "input.txt"; static const char filename_out[] = "output.txt"; size_t i = 0; size_t j = 0; FILE *file = fopen(filename, "r"); FILE *file_write = fopen(filename_out, "w"); char line[16]; // 动态分配指针数组,适配160万行的输入规模 const size_t max_lines = 1600001; char **line_array = malloc(max_lines * sizeof(char *)); if (file == NULL) { perror(filename); free(line_array); return 1; } if (line_array == NULL) { fprintf(stderr, "Failed to allocate memory for line array\n"); fclose(file); fclose(file_write); return 1; } while (fgets(line, sizeof line, file) != NULL) { // 移除换行符 line[strcspn(line, "\n")] = '\0'; // 检查是否超出动态数组容量 if (i < max_lines) { line_array[i++] = strdup(line); // 检查字符串复制是否成功 if (line_array[i-1] == NULL) { fprintf(stderr, "Failed to duplicate string at line %zu\n", i); break; } } else { fprintf(stderr, "Reached maximum line limit of %zu\n", max_lines); break; } } fclose(file); sort_a(line_array, i); if (file_write != NULL) { for (j = 0; j < i; j++) { fprintf(file_write, "%s\n", line_array[j]); } fclose(file_write); } else { perror(filename_out); } // 完整清理内存:先释放每个字符串,再释放指针数组 for (j = 0; j < i; j++) { free(line_array[j]); } free(line_array); return 0; } int cmpr(const void *a, const void *b) { return strcmp(*(const char **)a, *(const char **)b); } void sort_a(void *array, size_t n) { qsort(array, n, sizeof(char *), cmpr); }
关键改动说明
动态数组替换静态数组
用char **line_array = malloc(max_lines * sizeof(char *))在堆上分配指针数组,堆内存没有栈的大小限制,可轻松容纳百万级别的指针元素。内存安全检查
添加了malloc和strdup的失败检查,避免内存分配失败导致的程序崩溃,提升代码鲁棒性。变量类型优化
将计数变量i、j改为size_t类型——这是C标准中用于表示内存大小和计数的无符号类型,可避免整数溢出风险。完整内存清理
除了释放每个strdup分配的字符串,最后用free(line_array)释放动态数组本身,彻底避免内存泄漏。qsort兼容性
动态数组和静态数组在qsort中的用法完全一致,qsort仅需要数组起始地址、元素数量和单个元素的大小,与数组的内存分配位置无关。
可选:动态扩容逻辑(适配未知行数)
如果不确定输入文件的行数,可实现动态扩容,当当前数组容量不足时,用realloc将容量翻倍:
// 初始容量设为1000 size_t current_capacity = 1000; char **line_array = malloc(current_capacity * sizeof(char *)); // 在循环内检查并扩容 if (i >= current_capacity) { size_t new_capacity = current_capacity * 2; char **temp = realloc(line_array, new_capacity * sizeof(char *)); if (temp == NULL) { fprintf(stderr, "Failed to reallocate memory\n"); break; } line_array = temp; current_capacity = new_capacity; }
内容的提问来源于stack exchange,提问作者brentm
相关产品推荐
相关产品推荐

