繁体   English   中英

为什么该程序存在段错误?

[英]Why is this program segfaulting?

我编写了一个名为Mathtext的程序。 该程序通过将某些字符范围转换为Unicode范围(例如“数学字母样的符号”)来产生纯文本“样式”,以产生纯文本斜体,粗体,衬线等。

它像外壳一样,用作逐行解释器,在输入一行后输出翻译后的行。 这意味着可以将文件cat / piped in来翻译整个文件,以及您可以通过按^ 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

您的程序正在取消引用NULL,因为fgets在错误或EOF时返回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() (除非您要区分文件错误和文件结束)。

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();
}

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM