__builtin_unreachable()
据我在 GCC 7.3.0 上看到的,不会生成任何编译时警告
我在文档中也找不到任何暗示它会的东西。
例如,以下示例编译时没有任何警告:
#include <stdio.h>
int main(void) {
__builtin_unreachable();
puts("hello")
return 0;
}
和:
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -Wunreachable-code main.c
我认为它做的唯一一件事就是允许编译器根据永远不会到达某行代码的事实进行某些优化,如果你犯了编程错误并且它曾经犯过,则会给出未定义的行为。
例如,执行上述示例似乎正常退出,但未按hello
预期打印。然后,我们的装配分析表明,正常外观的出口只是 UB 巧合。
GCC的-fsanitize=unreachable
标志将 转换为__builtin_unreachable();
在运行时失败的断言:
<stdin>:1:17: runtime error: execution reached a __builtin_unreachable() call
但是,该标志在 Ubuntu 16.04 中已损坏:ld: unrecognized option '--push-state--no-as-needed'
对可执行文件有什么作用__builtin_unreachable()
?
如果我们使用和不__builtin_unreachable
使用 with 来反汇编代码:
objdump -S a.out
我们看到没有它的那个调用puts
:
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)
而没有的只做:
int main(void) {
5fa: 55 push %rbp
5fb: 48 89 e5 mov %rsp,%rbp
5fe: 66 90 xchg %ax,%ax
甚至没有返回,所以我认为这只是一个未定义的行为巧合,它并没有爆炸。
为什么 GCC 不能确定某些代码是否无法访问?
我收集了以下答案:
在 GCC 7.3.0、Ubuntu 18.04 上测试。