考虑以下代码:
#include <string_view>
constexpr std::string_view f() { return "hello"; }
static constexpr std::string_view g() {
auto x = f();
return x.substr(1, 3);
}
int foo() { return g().length(); }
如果我用 GCC 10.2 和 flags 编译它--std=c++17 -O1
,我会得到:
foo():
mov eax, 3
ret
此外,据我所知,此代码不会遇到任何未定义的行为问题。
但是 - 如果我添加 flag -fsanitize=undefined
,编译结果是:
.LC0:
.string "hello"
foo():
sub rsp, 104
mov QWORD PTR [rsp+80], 5
mov QWORD PTR [rsp+16], 5
mov QWORD PTR [rsp+24], OFFSET FLAT:.LC0
mov QWORD PTR [rsp+8], 3
mov QWORD PTR [rsp+72], 4
mov eax, OFFSET FLAT:.LC0
cmp rax, -1
jnb .L4
.L2:
mov eax, 3
add rsp, 104
ret
.L4:
mov edx, OFFSET FLAT:.LC0+1
mov rsi, rax
mov edi, OFFSET FLAT:.Lubsan_data154
call __ubsan_handle_pointer_overflow
jmp .L2
.LC1:
.string "/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/string_view"
.Lubsan_data154:
.quad .LC1
.long 287
.long 49
看到这个Compiler Explorer。
我的问题:为什么清理会干扰优化?特别是因为代码似乎没有任何 UB 危害......
笔记:
- 我怀疑是 GCC 错误,但也许我对 UBsan 所做的事情有错误的认识。
- 如果我设置相同的行为
-O3
。 - 在没有优化标志的情况下,无论是否经过清理,都会生成较长的代码。
- 如果您声明
x
为constexpr
变量,则清理不会阻止优化。 - 与 C++17 和 C++20 的行为相同。
- 使用 Clang,您也会得到这种差异,但只能使用更高的优化设置(例如
-O3
)。