代码之家  ›  专栏  ›  技术社区  ›  Delan Azabani

为什么这个程序会出错?

  •  4
  • Delan Azabani  · 技术社区  · 15 年前

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

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

    一切正常。但是,当我按^D并退出时,它会自动退出。我还是不太明白是什么原因造成的。

    编译 -g -O0

    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
    3 回复  |  直到 15 年前
        1
  •  3
  •   caf    15 年前

    大多数使用 feof() 是一个bug-这个程序在这个主循环中完美地演示了它:

    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();
    }
    
        2
  •  3
  •   Hasturkun    15 年前

    你的程序正在取消对NULL的引用,因为 fgets 在出现错误或EOF时返回NULL,您直接将其传递给transpose,transpose天真地使用结果。

        3
  •  1
  •   Karl Bielefeldt    15 年前

    feof fgets