假设我有这段带有 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/