gpt4 book ai didi

c++ - 为什么启用未定义的行为清理会干扰优化?

转载 作者:行者123 更新时间:2023-12-03 06:49:04 25 4
gpt4 key购买 nike

考虑以下代码:

#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 上看到这个.
我的问题:为什么 sanitizer 会干扰优化?特别是因为代码似乎没有任何 UB 危害......
笔记:
  • 我怀疑是 GCC 错误,但也许我对 UBsan 的作用有错误的看法。
  • 如果我设置了相同的行为 -O3 .
  • 在没有优化标志的情况下,更长的代码会在经过清理和不经过清理的情况下生成。
  • 如果您声明 x成为 constexpr变量,清理不会阻止优化。
  • 与 C++17 和 C++20 的行为相同。
  • 有了 Clang,你 get这种差异也是如此,但仅限于更高的优化设置(例如 -O3 )。
  • 最佳答案

    sanitizer 添加了必要的工具来检测运行时的违规行为。
    该检测可能会通过引入一些不透明的调用/副作用来阻止函数在编译时作为优化计算,否则这些调用/副作用不会在那里出现。
    您看到的不一致行为是因为 g().length();调用未在 constexpr 中完成上下文,因此不需要在编译时计算(好吧,“不期望”会更准确)。 GCC 可能有一些启发式计算 constexpr函数与 constexpr常规上下文中的参数一旦通过破坏 constexpr 就不会触发 sanitizer 。 - 函数的性质(由于添加了检测)或所涉及的启发式之一。
    添加 constexprx使 f()调用一个常量表达式(即使 g() 不是),所以它是在编译时编译的,所以不需要检测,这足以触发其他优化。
    人们可以将其视为 QoI 问题,但总的来说,这是有道理的

  • constexpr函数评估可能需要任意长的时间,因此除非被要求在编译时评估所有内容,否则并不总是可取的
  • 通过在常量表达式中使用此类函数,您始终可以“强制”进行此类评估(尽管在这种情况下标准有些宽松)。这也会为您处理任何 UB。
  • 关于c++ - 为什么启用未定义的行为清理会干扰优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64503440/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com