1

我试图通过转换以下两个不相关的类来理解对象的布局:

class A
{
public:
  A(int x):_a(x){}

private:
  int _a;
};

class B
{
public:
  void Show()
  {
    cout << "&_x = " << &_x << "," << " _x = " << _x << endl;
    cout << "&_y = " << &_y << "," << " _y = " << _y << endl;
    cout << "&_z = " << &_z << "," << " _z = " << _z << endl;
  }

private:
  int _x, _y, _z;
};

要测试类,主要有以下代码:

int main()
{
  A * pA = new A(5);
  cout << pA << endl;
  B * pB = (B *) pA;
  pB->Show();
}

据我了解,

  • 调用会成功
  • B::_x 的值为 A::_a
  • 在运行时,尝试访问 B::Show() 中的 B::_y 和 B::_z 应该会崩溃,因为该对象最初是 A 类型且大小为 4 字节,而编译器期望 _y 和 _z与大小为 12 字节的 B 对象的起始地址相距 4 和 8 字节的偏移量。

实际上,尽管使用 VS2010,在调试模式下,B::Show() 中的语句被打印并且 _y 和 _z 指向垃圾值,在发布模式下,语句被打印,并且 _y 和 _z 指向垃圾值,然后发生崩溃(仅有时:-()。

我预计我们应该在尝试访问 _y 和 _z 时立即观察到崩溃,因为它们必须指向未分配的内存,但这并没有发生。我知道这种情况应该属于“未定义行为”的范畴,但这种行为的可能解释是什么?

4

2 回答 2

0

这个问题没有实际效果,算了!

于 2013-08-06T11:56:23.573 回答
0

未定义行为的行为是未定义的。根据定义。

我们可以推测程序为什么会以不同的方式失败,但事实是它可能会每天发生变化,或者运行到运行,或者构建到构建。

于 2013-08-06T11:38:11.503 回答