如何向GCC提示一行在编译时不可访问?
编译器通常会提供一个。我还看到了一些库的宏,它们提供了 是否有一个提示,例如通过pragma或内置代码,我可以传递给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 {
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是第三个。如果您的编译器没有您需要的警告,可以使用静态分析器对其进行补充。我所说的那种分析器会有自己的注释语言和/或识别Cassert
,并使用它们来提示在特定执行点应该为真的属性。如果没有针对不可访问语句的特定注释,则可以使用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无法确定某些代码是否无法访问?
我