C语言对结构体数据使用qsort排序时触发Segmentation Fault段错误
问题根因
- qsort参数配置错误:你定义的
arr是Data*类型的指针数组,每个元素的大小为指针长度(64位系统8字节、32位系统4字节),但你调用qsort时第三个参数传了sizeof(Data),qsort交换元素时会越界读写内存,直接触发段错误。 - 比较函数参数解析错误:qsort传入比较函数的是数组元素的指针,你的数组元素是
Data*类型,因此pa、pb实际是Data**类型,你直接强转为Data*后访问成员,相当于把指针值当做结构体地址访问非法内存,触发段错误。 - 其余隐藏漏洞:
dest是double类型,直接做减法返回int会丢失小数部分,导致排序逻辑错误- 打印
dest时使用%d格式符,和double类型不匹配,输出异常 - 逐字段读取结构体效率低,若存在结构体字节对齐还可能出现读取错位
修正后代码
#include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <string.h> typedef struct Data_s { double dest; float dec; char colour[9]; short dress; int experience; char voyage; char care; unsigned short distance; int cars; char letter; unsigned char quick; char maelstrom; unsigned int station; short rat; long macey; float limb; } Data; int compare(const void *pa, const void * pb); int main(int argc, char** argv) { if (argc < 2) { printf("请传入文件路径参数\n"); return 1; } FILE* fp = fopen(argv[1],"rb"); if (!fp) { perror("文件打开失败"); return 1; } int fn = fileno(fp); struct stat sb; fstat(fn,&sb); #define NUM (int)(sb.st_size/sizeof(Data)) int i; Data *arr[NUM]; for(i = 0; i < NUM; i++) { arr[i] = (Data *)malloc(sizeof(Data)); // 直接读取整个结构体,无需逐字段读 fread(arr[i], sizeof(Data), 1, fp); } // 修正qsort第三个参数为指针数组元素的大小 qsort(arr, NUM, sizeof(Data*), compare); for(i = 0; i < NUM; i++) { // 修正打印double的格式符为%f printf("%f, ", arr[i]->dest); } printf("\n"); for(i = 0; i < NUM; i++) { free(arr[i]); } fclose(fp); return 0; } int compare (const void * pa, const void * pb) { // 先将参数转为Data**,解引用拿到实际的Data结构体指针 const Data *p1 = *(const Data **)pa; const Data *p2 = *(const Data **)pb; // 修正double比较逻辑,避免精度丢失 if (p1->dest > p2->dest) return 1; else if (p1->dest < p2->dest) return -1; else return 0; }
内容的提问来源于stack exchange,提问作者kirinM
相关产品推荐
相关产品推荐

