You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

std::as_writable_bytes何时触发UB?g函数是否无未定义行为?

关于reinterpret_cast、严格别名规则与std::span/std::as_writable_bytes的问题

代码示例

#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] == 0;
}

int h() {
    bool b{true};
    std::span<bool> bs(&b, 1);

    auto ps = std::as_writable_bytes(bs);
    ps[0] = std::byte{10};

    return b == 0;
}

问题解答

1. g函数是否无未定义行为?原因是什么?

g函数没有未定义行为,原因如下:

  • b是bool数组,数组元素的生命周期从初始化到函数结束持续有效。
  • std::span<bool>绑定数组是标准允许的合法操作,此时span代表数组中已存在的bool对象的连续视图。
  • 根据严格别名规则,用std::byte访问任何对象的字节表示是允许的。std::as_writable_bytes获取的是数组元素的字节级可写视图,修改ps[0]本质是直接修改数组中已存在的bool对象的字节内容,并未终止该对象的生命周期,完全符合标准要求。

2. 若g与h存在相同问题,std::as_writable_bytes的用途及正确用法是什么?

首先明确:g函数没有问题,仅h函数存在未定义行为。

  • 用途:std::as_writable_bytes用于获取连续存储对象(如数组、std::array、容器的连续存储段等)的可写字节视图,主要用于序列化、内存拷贝、字节级校验等底层字节操作场景。
  • 正确用法:
    • 仅用于操作已存在对象的字节表示,避免通过字节覆盖的方式“替换”对象(即防止因覆盖存储导致原对象生命周期意外终止)。
    • 优先绑定数组、std::span<T>(T为非特化类型,或特化但对应连续存储的场景如std::span<bool>绑定数组)这类明确包含持续生命周期对象的连续存储结构。
    • 若要修改单个标量对象的字节,建议用std::memcpy将字节数据复制到对象中,而非直接通过字节视图覆盖存储。

3. 为非数组元素创建std::span是否非法?

不非法。标准明确允许std::span绑定单个对象,通过std::span<T>(&obj, 1)的方式创建视图是合法的。h函数的问题并非出在创建span本身,而是后续通过字节视图覆盖单个标量对象的存储,导致原对象生命周期终止的操作。

4. 这些问题是否仅针对bool类型?

不是。该问题本质是单个标量对象的存储被字节覆盖后,原对象生命周期终止且未正确构造新对象导致的未定义行为,适用于所有标量类型(如int、char、double等)。例如将h函数中的bool替换为int,执行相同的字节覆盖操作,依然会触发未定义行为;而数组元素的字节修改操作,无论标量类型是什么,只要元素生命周期有效,就不会有问题。


内容的提问来源于stack exchange,提问作者Erik Man

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 02:12:29