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

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);
}

关键改动说明

  1. 动态数组替换静态数组
    用char **line_array = malloc(max_lines * sizeof(char *))在堆上分配指针数组,堆内存没有栈的大小限制,可轻松容纳百万级别的指针元素。

  2. 内存安全检查
    添加了malloc和strdup的失败检查,避免内存分配失败导致的程序崩溃,提升代码鲁棒性。

  3. 变量类型优化
    将计数变量i、j改为size_t类型——这是C标准中用于表示内存大小和计数的无符号类型,可避免整数溢出风险。

  4. 完整内存清理
    除了释放每个strdup分配的字符串,最后用free(line_array)释放动态数组本身,彻底避免内存泄漏。

  5. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 17:24:48