Bo *_*uan 2 c qsort segmentation-fault
我正在研究一个c程序来读取txt文件并对字符串进行排序.
data.txt中:
jk ef ab cd bc gh fg ij hi de
Run Code Online (Sandbox Code Playgroud)
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
int cmp(const void *p1, const void *p2) {
return strcmp(*(const char **)p1, *(const char **)p2);
}
int main() {
FILE *f = fopen("data.txt", "r");
char s[255][255];
char tmp[255];
int n = 0;
while (!feof(f)) {
fscanf(f, "%s", tmp);
strcpy(s[n], tmp);
n++;
}
fclose(f);
qsort(s, n, sizeof(char *), cmp);
int i = 0;
for (; i < n; i++) {
printf("%s ", s[i]);
}
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
我在Ubuntu上运行代码,它在段错误上打破了.相信这段错误发生在qsort我身上,我无法弄清楚原因.
有人可以给我一些建议吗?
比较函数是不正确的,因为您正在排序数组的数组char,您可以strcmp直接将指针传递给元素:
int cmp(const void *p1, const void *p2) {
return strcmp(p1, p2);
}
Run Code Online (Sandbox Code Playgroud)
但请注意,您的解析循环也是错误的:feof()不是检查文件结尾的正确方法.请改用:
n = 0;
while (n < 255 && fscanf(f, "%254s", s[n]) == 1) {
n++;
}
Run Code Online (Sandbox Code Playgroud)
所述qsortinvokation应该指定的数组元素的大小:
qsort(s, n, sizeof(*s), cmp);
Run Code Online (Sandbox Code Playgroud)
这是一个更正版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cmp(const void *p1, const void *p2) {
return strcmp(p1, p2);
}
int main(void) {
FILE *f = fopen("data.txt", "r");
char s[255][255];
char tmp[255];
int n = 0;
if (f == NULL)
return EXIT_FAILURE;
while (n < 255 && fscanf(f, "%254s", s[n]) == 1) {
n++;
}
fclose(f);
qsort(s, n, sizeof(*s), cmp);
for (int i = 0; i < n; i++) {
printf("%s ", s[i]);
}
printf("\n");
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
很多人都给出了很好的答案。
以下是您如何使用标准 GNU 工具自己一步一步找到它:
我们假设源文件名为q.c.
使用调试符号进行编译(注意这里不需要有 Makefile):
% make CFLAGS=-g q
cc -g q.c -o q
Run Code Online (Sandbox Code Playgroud)
现在,使用调试器 (gdb) 运行该程序:
% gdb q
(gdb) run
Starting program: /usr/home/fenyo/tmp/qs/q
Program received signal SIGSEGV, Segmentation fault.
0x00000008009607a6 in strcmp () from /lib/libc.so.7
Run Code Online (Sandbox Code Playgroud)
现在看一下堆栈帧:
(gdb) where
#0 0x00000008009607a6 in strcmp () from /lib/libc.so.7
#1 0x00000000004009b5 in cmp (p1=0x7ffffffeeb60, p2=0x7ffffffeeb88) at q.c:8
#2 0x000000080093b834 in qsort () from /lib/libc.so.7
#3 0x0000000000400af5 in main () at q.c:26
Run Code Online (Sandbox Code Playgroud)
所以你的问题在于qsort 库对你的函数的调用,它使用错误的指针调用 strcmp 。cmp
因此,我们从一个堆栈帧上升到您的 cmp 函数级别:
(gdb) up
#1 0x00000000004009b3 in cmp (p1=0x7ffffffeeb60, p2=0x7ffffffeeb88) at q.c:8
8 return strcmp( *(const char **) p1, *(const char **) p2);
Run Code Online (Sandbox Code Playgroud)
我们看p1的类型:
(gdb) ptype p1
type = void *
Run Code Online (Sandbox Code Playgroud)
由于 p1 是一个指针,我们检查其显示前 10 个字节的内容:
(gdb) print (*(char *) p1)@10
$43 = "jk\000\000\000\000\000\000\000"
Run Code Online (Sandbox Code Playgroud)
所以我们发现它是一个以 null 结尾的字符串,其中包含 jk.
所以你的演员阵容无效:*(const char **) p1。
这本来应该是(const char*) p1。
我们改变演员阵容然后它就起作用了。