使用qsort排序指针数组时首元素出现垃圾值的问题求助
问题根源与修复方案
核心错误1:指针数组内存分配错误
你创建双指针数组时用了calloc(wordcount, sizeof(char)),但string_array是char**类型,数组里每个元素是char*指针,正确的分配应该用sizeof(char*)(或sizeof(*string_array))。用sizeof(char)的话,每个元素只分配1字节,远小于指针的实际大小(通常4/8字节),直接导致数组元素内存被截断,后续赋值时破坏内存结构,出现垃圾值。
核心错误2:字符串未分配终止符空间
calloc(tok_len, sizeof(char))只分配了和token长度相等的空间,但C语言字符串必须靠末尾的'\0'标记结束。strncpy只会复制指定长度的字符,不会自动添加终止符,导致字符串没有结束标记,排序或打印时会读取到内存里的垃圾数据。
修复后的代码片段
char *token; // 修正指针数组的分配大小 char **string_array = calloc(wordcount, sizeof(char*)); if (!string_array){ fprintf(stderr, "couldn't make double pointer\n"); return; // 必须终止,避免空指针访问 } size_t str_array = 0; token = strtok(w2->data, "\n\t "); printf("token %ld: %s\n",str_array, token); size_t tok_len = strlen(token); // 分配字符串空间时+1,给'\0'留位置 string_array[str_array] = calloc(tok_len + 1, sizeof(char)); if (!string_array[str_array]){ fprintf(stderr, "could not find any of your words\n"); return; } strncpy(string_array[str_array], token, tok_len); string_array[str_array][tok_len] = '\0'; // 手动添加字符串终止符 str_array++; for (int x = 1; x<wordcount; x++){ token = strtok(NULL, "\n\t "); tok_len = strlen(token); string_array[str_array] = calloc(tok_len + 1, sizeof(char)); if (!string_array[str_array]){ fprintf(stderr, "failed somewhere with other tokens\n"); return; } printf("token %ld: %s\n",str_array, token); strncpy(string_array[str_array], token, tok_len); string_array[str_array][tok_len] = '\0'; str_array++; } qsort(string_array, str_array, sizeof(*string_array), lexsort); for (int x = 0; x<wordcount; x++){ printf("%s\n",string_array[x]); } // 记得释放内存,避免泄漏 for (int x = 0; x<wordcount; x++) { free(string_array[x]); } free(string_array); return; }
额外注意点
- 原代码中
if (!string_array)后没有加return,会继续执行后续代码触发空指针访问,必须补上。 strncpy的返回值是目标地址,除非目标为NULL否则不会返回NULL,原代码里的if (!strncpy(...))判断没有意义,直接手动添加终止符更可靠。- 所有动态分配的内存使用完后要释放,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Eli1776
相关产品推荐
相关产品推荐

