std::as_writable_bytes何时触发未定义的行为

问题描述 投票:0回答:1

我以为我终于理解了

reinterpret_cast
和严格别名,然后我遇到了这个示例,该示例是根据 https://en.cppreference.com/w/cpp/language/ub 上的“无效标量”示例稍作修改的

https://godbolt.org/z/jdY8brGha

#include <span> int g() { bool b[1] = {true}; std::span<bool> bs(b); auto ps = std::as_writable_bytes(bs); ps[0] = std::byte{10}; return b == 0; } int h() { bool b{true}; std::span<bool> bs(&b, sizeof(bool)); auto ps = std::as_writable_bytes(bs); ps[0] = std::byte{10}; return b == 0; }
从 godbolt 链接我可以看到 

g

 函数给出了我期望的汇编输出,而 
h
 则没有。我还了解到,当我从字节指针写入 
b
 函数中的 
h
 时,它的生命周期就会结束(类似于联合的工作方式),从而导致未定义的行为。我还认为 
g
 函数与此处的 as_bytes 示例类似:
https://en.cppreference.com/w/cpp/container/span/as_bytes

我的问题是:

g

函数是否没有未定义的行为?为什么/为什么不?

以及可能的后续问题:

如果

g

h
功能有同样的问题,
std::as_writable_bytes
的用途是什么以及如何正确使用它?在非数组元素上创建跨度是否非法?这些是否仅特定于 bool (我的测试似乎表明如此,但总是很难用未定义的行为来判断)?

c++ undefined-behavior reinterpret-cast strict-aliasing
1个回答
0
投票

b == 0

 中的 
g()
 询问 
b == nullptr
 是否为数组,因为 
b
 是一个数组(编译器将其优化为 
false
)。

你的函数

h()

应该有
std::span<bool> bs(&b, 1)
,因为你只有1个bool。

当前编写的第一个函数不受 UB 的影响,因为写入

b

 可能会使其具有陷阱表示,但你从未真正尝试从中读取。

但是将其更改为

return b[0] == false;

将使其具有与第二个函数相同的UB。

至于你的后续问题,你必须编写一个有效的对象表示:

int h() { bool b{true}; std::span<bool> bs(&b, 1); auto ps = std::as_writable_bytes(bs); bool f{false}; std::span<bool> fs(&f, 1); std::ranges::copy(std::as_bytes(fs), ps.begin()); return b == false; }
    
© www.soinside.com 2019 - 2024. All rights reserved.