gpt4 book ai didi

c++ - 奇怪的 Clang 行为

转载 作者:IT老高 更新时间:2023-10-28 22:38:11 25 4
gpt4 key购买 nike

看看这段代码:

#include <iostream>
#include <string>

void foo(int(*f)()) {
std::cout << f() << std::endl;
}

void foo(std::string(*f)()) {
std::string s = f();
std::cout << s << std::endl;
}

int main() {
auto bar = [] () -> std::string {
return std::string("bla");
};

foo(bar);

return 0;
}

编译

g++ -o test test.cpp -std=c++11

导致:

bla

就像它应该做的那样。用

编译它
clang++ -o test test.cpp -std=c++11 -stdlib=libc++

导致:

zsh: illegal hardware instruction  ./test

并用它编译

clang++ -o test test.cpp -std=c++11 -stdlib=stdlibc++

还导致:

zsh: illegal hardware instruction  ./test

Clang/GCC 版本:

clang version 3.2 (tags/RELEASE_32/final)
Target: x86_64-pc-linux-gnu
Thread model: posix

gcc version 4.7.2 (Gentoo 4.7.2-r1 p1.5, pie-0.5.5)

任何人有什么建议是怎么回事?

提前致谢!

最佳答案

是的,这是 Clang++ 中的一个错误。我可以在 i386-pc-linux-gnu 中使用 CLang 3.2 重现它。

现在进行一些随机分析...

我发现错误在于从 labmda 到指针函数的转换:编译器创建了一种 thunk 具有调用 lambda 的适当签名,但它具有指令 ud2 而不是 ret

你可能都知道,ud2 指令是一条明确引发“无效操作码”异常的指令。也就是说,一条指令故意未定义。

看看反汇编:这是thunk函数:

main::$_0::__invoke():
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl 8(%ebp), %eax
movl %eax, (%esp)
movl %ecx, 4(%esp)
calll main::$_0::operator()() const ; this calls to the real lambda
subl $4, %esp
ud2 ; <<<-- What the...!!!

因此,该错误的一个最小示例将是:

int main() {
std::string(*f)() = [] () -> std::string {
return "bla";
};
f();
return 0;
}

奇怪的是,如果返回类型是简单类型,例如 int,则该错误不会发生。那么生成的thunk就是:

main::$_0::__invoke():
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl %eax, (%esp)
calll main::$_0::operator()() const
addl $8, %esp
popl %ebp
ret

我怀疑问题出在返回值的转发上。如果它适合一个寄存器,例如 eax 一切顺利。但是如果是一个很大的struct,比如std::string,在栈中返回的话,编译器就会一头雾水,绝望地发出ud2

关于c++ - 奇怪的 Clang 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15798478/

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