reinterpret_cast<std::string*> 在 gcc 上导致分段错误但在 clang 上有效
reinterpret_cast<std::string*> cause segmentation fault on gcc but works on 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 buffer = new std::byte[1024];
std::string str = "hello";
store_rvalue_string(buffer, std::move(str));
}
这是一个严格的别名违规,因此是 UB。
一个不太正式的答案是,你在一块内存上调用 std::basic_string::operator=
,而 string
构造函数一开始就没有被调用过。
我的猜测是,在 Clang 上,内存恰好用零填充,并且用零字节填充的字符串在标准库实现中算作空。
正确的解决方案是使用 placement-new,创建一个 new 对象(通过调用其构造函数):
new(buffer) std::string(std::move(str));
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));
}
这是一个严格的别名违规,因此是 UB。
一个不太正式的答案是,你在一块内存上调用 std::basic_string::operator=
,而 string
构造函数一开始就没有被调用过。
我的猜测是,在 Clang 上,内存恰好用零填充,并且用零字节填充的字符串在标准库实现中算作空。
正确的解决方案是使用 placement-new,创建一个 new 对象(通过调用其构造函数):
new(buffer) std::string(std::move(str));