Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何向GCC提示一行在编译时不可访问?_C_Gcc_Pragma_Built In_Unreachable Code - Fatal编程技术网

如何向GCC提示一行在编译时不可访问?

如何向GCC提示一行在编译时不可访问?,c,gcc,pragma,built-in,unreachable-code,C,Gcc,Pragma,Built In,Unreachable Code,编译器通常会提供一个。我还看到了一些库的宏,它们提供了 是否有一个提示,例如通过pragma或内置代码,我可以传递给GCC(或任何其他编译器),如果确定实际可以到达预期无法到达的行,则在编译过程中会发出警告或出错? 下面是一个例子: if (!conf->devpath) { conf->devpath = arg; return 0; } // pass other opts into fuse else {

编译器通常会提供一个。我还看到了一些库的宏,它们提供了

是否有一个提示,例如通过pragma或内置代码,我可以传递给GCC(或任何其他编译器),如果确定实际可以到达预期无法到达的行,则在编译过程中会发出警告或出错?

下面是一个例子:

    if (!conf->devpath) {
        conf->devpath = arg;
        return 0;
    } // pass other opts into fuse
    else {
        return 1;
    }
    UNREACHABLE_LINE();

这一点的价值在于,在预期不可访问行以上的条件发生变化后,检测该行实际上是可访问的。

如果编译器没有您需要的警告,可以使用静态分析器对其进行补充。我所说的那种分析器会有自己的注释语言和/或识别C
assert
,并使用它们来提示在特定执行点应该为真的属性。如果没有针对不可访问语句的特定注释,则可以使用
assert(false)


我个人并不熟悉它们,但Klokwork和CodeSonar是两个著名的分析器。Goanna是第三个。

如果您的编译器没有您需要的警告,可以使用静态分析器对其进行补充。我所说的那种分析器会有自己的注释语言和/或识别C
assert
,并使用它们来提示在特定执行点应该为真的属性。如果没有针对不可访问语句的特定注释,则可以使用
assert(false)


我个人并不熟悉它们,但Klokwork和CodeSonar是两个著名的分析器。Goanna是第三个。

gcc 4.5支持编译器内联,将其与
结合使用-Wunreachable code
可能会执行您想要的操作,但可能会导致虚假警告gcc 4.5支持编译器内联,将其与
结合使用-Wunreachable code
可能会执行您想要的操作,但是使用gcc 4.4.0 Windows交叉编译器到PowerPC使用-O2或-O3编译时,可能会导致虚假警告。以下内容适用于我:

#define unreachable asm("unreachable\n")
如果编译器没有对未知操作进行优化,则汇编程序会因未知操作而失败,因为它已得出无法访问的结论


是的,它很可能“在不同的优化选项下高度不可预测”,并且在我最终更新编译器时可能会中断,但目前它比什么都没有好。

使用gcc 4.4.0 Windows交叉编译器到PowerPC使用-O2或-O3编译,以下对我来说很有用:

#define unreachable asm("unreachable\n")
如果编译器没有对未知操作进行优化,则汇编程序会因未知操作而失败,因为它已得出无法访问的结论


是的,它很可能“在不同的优化选项下是高度不可预测的”,并且在我最终更新编译器时可能会中断,但目前它比什么都没有要好。

\uuuu builtin\u unreachable()
在GCC 7.3.0上看不到任何编译时警告。

我在文件中也找不到任何暗示它会的东西

例如,以下示例编译时没有任何警告:

#include <stdio.h>

int main(void) {
    __builtin_unreachable();
    puts("hello")
    return 0;
}
我认为它所做的唯一一件事是,允许编译器根据从未达到某一行代码这一事实进行某些优化,并在出现编程错误时给出未定义的行为

例如,执行上述示例似乎会正常退出,但不会按预期打印
hello
。我们的装配分析表明,正常外观的出口只是一个巧合

GCC的
-fsanize=unreachable
标志转换
\u内置的\u unreachable()
<stdin>:1:17: runtime error: execution reached a __builtin_unreachable() call
我们看到没有它的一个调用
put

000000000000063a <main>:
#include <stdio.h>

int main(void) {
 63a:   55                      push   %rbp
 63b:   48 89 e5                mov    %rsp,%rbp
    puts("hello");
 63e:   48 8d 3d 9f 00 00 00    lea    0x9f(%rip),%rdi        # 6e4 <_IO_stdin_used+0x4>
 645:   e8 c6 fe ff ff          callq  510 <puts@plt>
    return 0;
 64a:   b8 00 00 00 00          mov    $0x0,%eax
}
 64f:   5d                      pop    %rbp
 650:   c3                      retq
 651:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
 658:   00 00 00
 65b:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
甚至没有回来,所以我认为这只是一个未定义的行为巧合,它没有爆炸

为什么GCC无法确定某些代码是否无法访问?

我收集了以下答案:

  • 出于某种原因,自动确定无法访问的代码对于GCC来说太难了,这就是为什么多年来,
    -Wunreachable code
    什么都不做的原因:

  • 用户可以使用内联程序集,这意味着无法访问,但GCC无法确定这一点。其中提到:

    其中一种情况是紧跟在永不终止的asm语句之后,或者紧跟在将控制权转移到其他位置且永不返回的asm语句之后。在本例中,如果没有uu builtin_unreachable,GCC将发出警告,指出控件已到达非void函数的末尾。它还生成要在asm之后返回的代码

    int f (int c, int v)
    {
      if (c)
        {
          return v;
        }
      else
        {
          asm("jmp error_handler");
          __builtin_unreachable ();
        }
    }
    

在GCC 7.3.0和Ubuntu18.04上测试。

\uuuu builtin\uUnreachable()
在GCC 7.3.0上看不到任何编译时警告

我在文件中也找不到任何暗示它会的东西

例如,以下示例编译时没有任何警告:

#include <stdio.h>

int main(void) {
    __builtin_unreachable();
    puts("hello")
    return 0;
}
我认为它所做的唯一一件事是,允许编译器根据从未达到某一行代码这一事实进行某些优化,并在出现编程错误时给出未定义的行为

例如,执行上述示例似乎会正常退出,但不会按预期打印
hello
。我们的装配分析表明,正常外观的出口只是一个巧合

GCC的
-fsanize=unreachable
标志转换
\u内置的\u unreachable()
<stdin>:1:17: runtime error: execution reached a __builtin_unreachable() call
我们看到没有它的一个调用
put

000000000000063a <main>:
#include <stdio.h>

int main(void) {
 63a:   55                      push   %rbp
 63b:   48 89 e5                mov    %rsp,%rbp
    puts("hello");
 63e:   48 8d 3d 9f 00 00 00    lea    0x9f(%rip),%rdi        # 6e4 <_IO_stdin_used+0x4>
 645:   e8 c6 fe ff ff          callq  510 <puts@plt>
    return 0;
 64a:   b8 00 00 00 00          mov    $0x0,%eax
}
 64f:   5d                      pop    %rbp
 650:   c3                      retq
 651:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
 658:   00 00 00
 65b:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
甚至没有回来,所以我认为这只是一个未定义的行为巧合,它没有爆炸

为什么GCC无法确定某些代码是否无法访问?