使用stdlib.c的qsort()按字符串第3位数字排序触发SIGSEGV错误排查
问题分析与解决方案
你的段错误问题确实出在类型转换和qsort参数的错误上,还有一个容易忽略的下标问题,我帮你拆解清楚:
核心错误点
1. qsort的元素大小参数错误
你调用qsort时传了sizeof(char),但你的数组string_mix是char*类型的数组(每个元素是指向字符串的指针),单个元素的大小应该是sizeof(char*)(通常是4或8字节,取决于平台)。传sizeof(char)会让qsort以1字节为步长遍历数组,完全错误地访问内存,直接导致非法内存访问。
2. 对比函数的类型转换错误
qsort传给对比函数的a和b参数,是指向数组元素的指针——也就是说,你的数组元素是char*,那么a和b的实际类型是char**。你直接把void*转成const char*,相当于把指针的内存地址当成了字符串的首地址去访问,这必然会触发段错误。
3. 字符串下标错误
你提到每个字符串的第3位是数字,但C语言的字符串下标是从0开始计数的:第1位是[0],第2位是[1],第3位是[2]。原来的代码用ia[3]取的是第4个字符,这会导致你比较的不是预期的数字,即使没崩溃,排序结果也不对。
修正后的代码
修正qsort调用
qsort(string_mix, (size_t)(k - 1), sizeof(char*), compare_at3);
修正对比函数
int compare_at3(const void* a, const void* b){ static int k = 1; // 先把void*转成指向char*的指针,再解引用拿到字符串指针 const char *ia = *(const char**)a; const char *ib = *(const char**)b; printf("In compare_at3 %d iter\n", k++); // 取第3位(下标2)的数字进行比较 int num_a = ia[2] - '0'; int num_b = ib[2] - '0'; return num_a - num_b; }
验证示例
我写了一个完整的可运行示例,你可以参考:
#include <stdio.h> #include <stdlib.h> #define MAX_NO_OF_STRINGS 10 int compare_at3(const void* a, const void* b){ static int k = 1; const char *ia = *(const char**)a; const char *ib = *(const char**)b; printf("In compare_at3 %d iter\n", k++); int num_a = ia[2] - '0'; int num_b = ib[2] - '0'; return num_a - num_b; } int main() { char* string_mix[MAX_NO_OF_STRINGS] = {"aob3l", "gou5!", "oib1k", "llp6d"}; int k = 5; // 假设k-1是数组中有效元素的数量 qsort(string_mix, (size_t)(k - 1), sizeof(char*), compare_at3); // 打印排序结果 for (int i = 0; i < k-1; i++) { printf("%s ", string_mix[i]); } printf("\n"); return 0; }
运行这段代码会输出你预期的结果:oib1k aob3l gou5! llp6d,而且不会触发段错误。
内容的提问来源于stack exchange,提问作者user6306428
相关产品推荐
相关产品推荐

