【发布时间】:2011-11-09 17:00:04
【问题描述】:
【问题讨论】:
标签: c++ object undefined-behavior
【问题讨论】:
标签: c++ object undefined-behavior
正如其他答案中指出的那样,联合是最明显的安排方式。
这是一个更清晰的示例,说明内置赋值运算符可能如何产生部分重叠的对象。如果不是部分重叠的对象限制,此示例将不会显示 UB。
union Y {
int n;
short s;
};
void test() {
Y y;
y.s = 3; // s is the active member of the union
y.n = y.s; // Although it is valid to read .s and then write to .x
// changing the active member of the union, .n and .s are
// not of the same type and partially overlap
}
即使是相同类型的对象,您也可能会出现部分重叠。在不向X 添加填充的实现中,考虑short 严格大于char 的示例。
struct X {
char c;
short n;
};
union Y {
X x;
short s;
};
void test() {
Y y;
y.s = 3; // s is the active member of the union
y.x.n = y.s; // Although it is valid to read .s and then write to .x
// changing the active member of the union, it may be
// that .s and .x.n partially overlap, hence UB.
}
【讨论】:
union 就是一个很好的例子。
您可以创建具有重叠成员的内存结构。
例如(来自 MSDN):
union DATATYPE // Declare union type
{
char ch;
int i;
long l;
float f;
double d;
} var1;
现在,如果您使用分配 char 成员,则所有其他成员都未定义。那是因为它们在同一个内存块上,而你只为它的一部分设置了一个实际值:
DATATYPE blah;
blah.ch = 4;
如果您随后尝试访问 blah.i 或 blah.d 或 blah.f,它们将具有未定义的值。 (因为只有第一个字节,它是一个字符,设置了它的值)
【讨论】:
blah.ch = 4; blah.i = blah.ch; 以避免与联合可用的其他 UB 混淆。
这是指指针别名的问题,在 C++ 中是禁止的,以使编译器更容易优化。可以在this thread中找到对该问题的一个很好的解释
【讨论】:
他的意思是严格的别名规则吗?内存中的对象不应与其他类型的对象重叠。
“严格别名是由 C(或 C++)编译器做出的一个假设,即取消引用指向不同类型对象的指针永远不会引用相同的内存位置(即相互别名。)”
【讨论】:
典型的例子是使用 memcpy:
char *s = malloc(100);
int i;
for(i=0; i != 100;++i) s[i] = i; /* just populate it with some data */
char *t = s + 10; /* s and t may overlap since s[10+i] = t[i] */
memcpy(t, s, 20); /* if you are copying at least 10 bytes, there is overlap and the behavior is undefined */
memcpy 是未定义行为的原因是因为没有执行复制所需的算法。在这种情况下,memmove 被引入作为一种安全的替代方案。
【讨论】: