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

字符数组调用qsort出现段错误,求问题定位与解决

调用qsort排序字符串常量触发段错误的原因及修复方案

问题根源

你传递给qsort的是字符串字面量(代码中用双引号直接定义的字符串,比如"abvasfa"),这类字符串在程序运行时存储在只读数据段(如Linux下的.rodata)中。qsort排序时会修改数组元素的内存位置,尝试写入只读内存会直接触发段错误(内存访问违规)。

你的代码里,main函数传入的"abvasfa"和"avbasda"是const char*类型的常量,但checkPermutation_sort的参数声明为char*,编译器可能不会强制报错,但运行时修改只读内存的行为是C标准定义的未定义行为,必然导致崩溃。

修复方案

核心思路:不要直接对字符串常量调用qsort,先将字符串复制到可修改的内存区域(栈数组或堆内存),再对副本排序。

方案1:使用堆内存分配副本(通用场景)

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

int cmpfnc (const void *a, const void *b) {
    return *(const char *)a - *(const char *)b;
}

int checkPermutation_sort (const char *s1, const char *s2) {
    int l1 = strlen(s1);
    int l2 = strlen(s2);
    if (l1 != l2) return -1;
    
    // 分配可修改的内存副本
    char *copy1 = malloc(l1 + 1);
    char *copy2 = malloc(l2 + 1);
    if (!copy1 || !copy2) {
        free(copy1);
        free(copy2);
        return -1; // 内存分配失败处理
    }
    strcpy(copy1, s1);
    strcpy(copy2, s2);
    
    // 对副本排序
    qsort(copy1, l1, sizeof(char), cmpfnc);
    qsort(copy2, l2, sizeof(char), cmpfnc);
    
    // 比较结果
    int result = strcmp(copy1, copy2);
    
    // 释放堆内存
    free(copy1);
    free(copy2);
    
    return result;
}

int main () {
    printf("%d\n", checkPermutation_sort("abvasfa", "avbasda"));
    return 0;
}

方案2:使用栈数组(适合字符串长度较小且固定的场景)

如果能确定输入字符串的最大长度,用栈数组更高效,无需手动管理内存:

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

int cmpfnc (const void *a, const void *b) {
    return *(const char *)a - *(const char *)b;
}

int checkPermutation_sort (const char *s1, const char *s2) {
    int l1 = strlen(s1);
    int l2 = strlen(s2);
    if (l1 != l2) return -1;
    
    // 栈数组存储副本(假设字符串长度不超过99)
    char copy1[100], copy2[100];
    strcpy(copy1, s1);
    strcpy(copy2, s2);
    
    qsort(copy1, l1, sizeof(char), cmpfnc);
    qsort(copy2, l2, sizeof(char), cmpfnc);
    
    return strcmp(copy1, copy2);
}

int main () {
    printf("%d\n", checkPermutation_sort("abvasfa", "avbasda"));
    return 0;
}

补充说明

从你提供的gdb调试信息可以看到,s1的地址是0x55555555600c,这个地址属于程序的只读数据区。当qsort内部执行memmove等操作尝试修改该区域内存时,就会触发段错误,这和我们分析的原因完全吻合。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 17:16:03