gpt4 book ai didi

c++ - 为什么局部静态对象的初始化使用隐藏的保护标志?

转载 作者:太空狗 更新时间:2023-10-29 20:53:15 25 4
gpt4 key购买 nike

C++ 中的局部静态对象在第一次需要时初始化一次(如果初始化有副作用,这是相关的):

void once() {
static bool b = [] {
std::cout << "hello" << std::endl; return true;
} ();
}

once 将在第一次调用时打印“hello”,但如果再次调用则不会。

我已将此模式的一些变体放入 Compiler Explorer 中并注意到所有大牌实现(GCC、Clang、ICC、VS)本质上都做同样的事情:创建一个隐藏变量 guard variable for once()::b 并检查查看主变量是否需要“这次”初始化;如果是,就初始化,然后设置守卫,下次就不会跳出初始化代码了。例如(通过调用 extern bool init_b(); 替换 lambda 来最小化):

once():
movzx eax, BYTE PTR guard variable for once()::b[rip]
test al, al
je .L16
ret
.L16:
push rbx
mov edi, OFFSET FLAT:guard variable for once()::b
call __cxa_guard_acquire
test eax, eax
jne .L17
pop rbx
ret
.L17:
call init_b()
pop rbx
mov edi, OFFSET FLAT:guard variable for once()::b
jmp __cxa_guard_release
mov rbx, rax
mov edi, OFFSET FLAT:guard variable for once()::b
call __cxa_guard_abort
mov rdi, rbx
call _Unwind_Resume

...来自带有 -O3 的 GCC 6.3。

这并非不合理,而且我知道在实践中,只要条件一致,条件跳转就几乎是免费的。然而,我的直觉仍然是通过un有条件地跳转到初始化代码来实现它,作为它的最后一个 Action ,它会用 nop 指令覆盖原始跳转。不一定是每个平台上的选项,但 x86 系列似乎对您可以读取或写入的内容以及在何处相当自由。

这个看似简单但没有主流编译器使用的想法有什么问题? (或者我是否只需要更努力地尝试示例?)

最佳答案

这种“优化”在多线程环境中是不安全的,即使在单线程环境中也可能不安全。

“nops”的编写可能需要多条指令。

在优化最终代码之前,可能无法知道 jmp 指令的大小(是否需要 8、16 或 32 位偏移量?)

CPU 中的指令缓存不会接收到代码字节的变化,除非执行指令子集之一导致缓存被刷新。

所有这些都假设代码可以通过数据段写入。

关于c++ - 为什么局部静态对象的初始化使用隐藏的保护标志?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43413237/

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