C++ 重新解释铸造<;标准::字符串*>;在gcc上导致分段错误,但在clang上起作用

C++ 重新解释铸造<;标准::字符串*>;在gcc上导致分段错误,但在clang上起作用,c++,gcc,clang,C++,Gcc,Clang,gcc和clang版本都是11,下面是示例代码 #include <string> #include <cstddef> void store_rvalue_string(std::byte* buffer, std::string&& value) { *reinterpret_cast<std::string*>(buffer) = std::move(value); } int main() { auto buff

gcc和clang版本都是11,下面是示例代码

#include <string>
#include <cstddef>


void store_rvalue_string(std::byte* buffer, std::string&& value) {
    *reinterpret_cast<std::string*>(buffer) = std::move(value);
}


int main() {
    auto buffer = new std::byte[1024];
    std::string str = "hello";
    store_rvalue_string(buffer, std::move(str));
}
#包括
#包括
无效存储值字符串(标准::字节*缓冲区,标准::字符串和值){
*重新解释强制转换(缓冲)=标准::移动(值);
}
int main(){
自动缓冲区=新标准::字节[1024];
std::string str=“hello”;
存储值字符串(缓冲区,std::move(str));
}

这是一种严格的别名冲突,因此是UB

一个不太正式的回答是,您在一段内存上调用
std::basic_string::operator=
,而该内存的
string
构造函数从一开始就没有被调用过

我的猜测是,在Clang上,内存恰好被零填充,而在标准库实现中,填充了零字节的字符串被视为空

正确的解决方案是使用placement new来创建新对象(通过调用其构造函数):


这是一种严格的别名冲突,因此是UB

一个不太正式的回答是,您在一段内存上调用
std::basic_string::operator=
,而该内存的
string
构造函数从一开始就没有被调用过

我的猜测是,在Clang上,内存恰好被零填充,而在标准库实现中,填充了零字节的字符串被视为空

正确的解决方案是使用placement new来创建新对象(通过调用其构造函数):


这不是一个有效的C++代码。这不是一个有效的C++代码…和
newstd::byte[1024]
可以替换为
新的std::byte[sizeof(std::string)]或与两个。。。和
newstd::byte[1024]
可以替换为
新的std::byte[sizeof(std::string)]或带有两个
new(buffer) std::string(std::move(str));