c++ - 空结构(或结构填充)可以有任意值吗?

标签 c++ language-lawyer undefined-behavior

假设我有这段带有 UB 的代码:

union Flag {
    constexpr Flag() : empty{} {}

    struct {} empty;
    bool value;
};

static Flag flag;

int main() {
    return flag.value;
}

UB 访问的位置 value当它不是 union 的活跃成员时Flag .

目前,UBSan 不会捕获此错误,因为(据我所知)UBSan 没有办法检查 union 的最后一个书面成员。对于这种特殊情况,我认为 UBSan 可以通过对 bool 类型的非真/假值进行相同的检查,间接捕获此处发生的一些 UB。如果一个空结构的字节被认为是“未初始化的”或“可以有任意值”,那么编译器可以合法地将这个空结构的任意字节设置为任何非零/一值,然后 UBSan 将能够捕获 bool 的无效值的负载。

我想知道的是:在语义上是否允许将空结构的标称字节——更一般地说,所有结构中的任何填充字节——初始化为任何非零模式?

最佳答案

Is it semantically permissible to have the nominal byte of empty structs–and more generally, any padding bytes in all structs–be initialized to any non-zero pattern?

就编译器而言,任何不属于类型值表示的字节都是公平游戏。好吧,在某种程度上。

您可以有效地将 memcpy 转换为此类字节,但这仅在源数据(直接或间接)来自该类型的现有对象时才有效。这来自 [basic.types]/2&3。因此,在对象模型中,用户无法将任何内容放入该存储空间。

因此,对于 C++ 对象模型中的代码,允许实现使用填充字节的内容。

C++20 的隐式对象创建规则使这变得更加困难,因为它允许未初始化的对象显示在已经有字节的存储中。这些表现通常与 placement-new 之类的代码无关,因此 UBSan 很难初始化这样的东西。

您展示的 union 是隐式生命周期(由于简单的复制/移动构造函数),因此用户可以玩这些东西。

关于c++ - 空结构(或结构填充)可以有任意值吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72654285/

相关文章:

c++ - 使用结构本身的类型定义结构参数

c++ - 持续的 ASIO 连接

c++ - clang 6 和 clang 7 模板转换运算符区别

c++ - 返回到转换构造函数中的仅 move 类型

c - 我是否误解了这个关于字符串文字范围的例子?

c++ - 超出 C++ 的界限和未定义的行为

c++ - 关于在需要常量表达式的上下文中使用的泛左值常量表达式的问题

c++ - 在编译时不知道父类的情况下传递带括号的函数指针

c++ - 如何检查 int 变量是否包含合法(非陷阱表示)值?

c++ - 检查 float 是否可以表示为整型