C 为什么这个程序会出错?

C 为什么这个程序会出错?,c,shell,eof,C,Shell,Eof,我写了一个程序叫。该程序通过将某些字符范围转换为Unicode范围(如“数学字母符号”)来生成纯文本斜体、粗体、衬线等,从而提供纯文本“样式” 它作为一个逐行解释器工作,就像shell一样,在输入一行后输出翻译的行。这意味着可以通过管道将文件cat/导入以翻译整个文件,也可以通过按^D来“退出”shell,这是由stdin点击EOF检测到的 一切都正常。但是,当我按下^D并退出时,它会出现故障。我仍然不能完全理解是什么导致了这种情况 使用-g-O0编译有一点帮助;我现在知道,当按下^D时,在转置

我写了一个程序叫。该程序通过将某些字符范围转换为Unicode范围(如“数学字母符号”)来生成纯文本斜体、粗体、衬线等,从而提供纯文本“样式”

它作为一个逐行解释器工作,就像shell一样,在输入一行后输出翻译的行。这意味着可以通过管道将文件
cat
/导入以翻译整个文件,也可以通过按^D来“退出”shell,这是由stdin点击EOF检测到的

一切都正常。但是,当我按下^D并退出时,它会出现故障。我仍然不能完全理解是什么导致了这种情况

使用
-g-O0
编译有一点帮助;我现在知道,当按下^D时,在转置中调用strlen会产生问题。但是,在^D期间不应调用转置,因为eof是真的

Program received signal SIGSEGV, Segmentation fault. __strlen_sse2 () at ../sysdeps/x86_64/multiarch/../strlen.S:31 31 ../sysdeps/x86_64/multiarch/../strlen.S: No such file or directory. in ../sysdeps/x86_64/multiarch/../strlen.S (gdb) where #0 __strlen_sse2 () at ../sysdeps/x86_64/multiarch/../strlen.S:31 #1 0x0000000000400b0e in transpose (s=0x0, capsDelta=120263, smallDelta=120257, numDelta=0) at mathtext.c:58 #2 0x0000000000400e2b in main (argc=2, argv=0x7fffffffe4b8) at mathtext.c:92 程序接收信号SIGSEGV,分段故障。 __strlen_sse2()位于../sysdeps/x86_64/multiarch/。/strlen.S:31 31../sysdeps/x86_64/multiarch/。/strlen.S:没有这样的文件或目录。 在../sysdeps/x86_64/multiarch/。/strlen.S中 (gdb)在哪里 #0_ustrlen_sse2()位于../sysdeps/x86_64/multiarch/。/strlen.S:31 #1 0x0000000000400b0e在mathtext的转置中(s=0x0,capsDelta=120263,smallDelta=120257,numDelta=0)。c:58
#2个0x0000000000400e2b在主(argc=2,argv=0x7fffffffe4b8)在mathtext.c:92中,您的程序正在取消对NULL的引用,因为
fgets
在出错或EOF时返回NULL,您直接将其传递给transpose,transpose会天真地使用结果。

feof
无法预测未来。在实际按下^D键之前,它不知道文件结束了,此时您的程序将返回w在
fgets
中等待输入。读取文件不会产生错误,因为所有输入在开始时都已存在。请检查转置函数中是否为NULL。

大多数
feof()
的使用都是一个错误-此程序在这个主循环中完美地演示了这一点:

char temp[1048576];
do {
    if (!strcmp(argv[1], "serifb"))
        transpose(fgets(temp, 1048576, stdin), 119808 - 'A', 119834 - 'a', 120782 - '0');
    else if (!strcmp(argv[1], "serifi"))
        transpose(fgets(temp, 1048576, stdin), 119860 - 'A', 119886 - 'a', 0);
    else if (!strcmp(argv[1], "serifbi"))
        transpose(fgets(temp, 1048576, stdin), 119912 - 'A', 119938 - 'a', 0);
    else if (!strcmp(argv[1], "sans"))
        transpose(fgets(temp, 1048576, stdin), 120224 - 'A', 120250 - 'a', 120802 - '0');
    else if (!strcmp(argv[1], "sansb"))
        transpose(fgets(temp, 1048576, stdin), 120276 - 'A', 120302 - 'a', 120812 - '0');
    else if (!strcmp(argv[1], "sansi"))
        transpose(fgets(temp, 1048576, stdin), 120328 - 'A', 120354 - 'a', 0);
    else if (!strcmp(argv[1], "sansbi"))
        transpose(fgets(temp, 1048576, stdin), 120380 - 'A', 120406 - 'a', 0);
    else if (!strcmp(argv[1], "mono"))
        transpose(fgets(temp, 1048576, stdin), 120432 - 'A', 120458 - 'a', 120822 - '0');
    else if (!strcmp(argv[1], "fullwidth"))
        transposeBlock(fgets(temp, 1048576, stdin), '!', '~', 65281 - '!');
    else return help();
} while(!feof(stdin));
在文件末尾,
fgets()
将返回
NULL
,然后下一次调用
feof()
将返回true。因此正确的方法是测试输入函数的返回值-既然您正在进行该测试,就不需要调用
feof()
(除非您想区分文件错误和文件结尾)


请在mathtext的第92行附近显示代码。更简单的说法是:在读取超过EOF之前,不会设置EOF。最后一次有效读取将读取到EOF,但不会超过EOF,因此失败的读取将正好有0个字节可读取。
char temp[1048576];
while (fgets(temp, sizeof temp, stdin) != NULL) {
    if (!strcmp(argv[1], "serifb"))
        transpose(temp, 119808 - 'A', 119834 - 'a', 120782 - '0');
    else if (!strcmp(argv[1], "serifi"))
        transpose(temp, 119860 - 'A', 119886 - 'a', 0);
    else if (!strcmp(argv[1], "serifbi"))
        transpose(temp, 119912 - 'A', 119938 - 'a', 0);
    else if (!strcmp(argv[1], "sans"))
        transpose(temp, 120224 - 'A', 120250 - 'a', 120802 - '0');
    else if (!strcmp(argv[1], "sansb"))
        transpose(temp, 120276 - 'A', 120302 - 'a', 120812 - '0');
    else if (!strcmp(argv[1], "sansi"))
        transpose(temp, 120328 - 'A', 120354 - 'a', 0);
    else if (!strcmp(argv[1], "sansbi"))
        transpose(temp, 120380 - 'A', 120406 - 'a', 0);
    else if (!strcmp(argv[1], "mono"))
        transpose(temp, 120432 - 'A', 120458 - 'a', 120822 - '0');
    else if (!strcmp(argv[1], "fullwidth"))
        transposeBlock(temp, '!', '~', 65281 - '!');
    else return help();
}