Рассмотрим следующий код:
#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 и флагами --std=c++17 -O1
, я получу:
foo():
mov eax, 3
ret
также, насколько мне известно, этот код не страдает от каких-либо проблем с неопределенным поведением.
Однако, если я добавлю флаг -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
).
mov eax, 3
все еще там, и нет вызововf
илиg
. Он просто добавил инструментарий (который, по общему признанию, здесь не нужен). - person interjay   schedule 23.10.2020