【问题标题】:casting and object layout铸造和对象布局
【发布时间】:2013-08-07 09:14:19
【问题描述】:

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

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 时立即观察到崩溃,因为它们必须指向未分配的内存,但这并没有发生。我知道这种情况应该属于“未定义行为”的范畴,但这种行为的可能解释是什么?

【问题讨论】:

  • 没有“应该崩溃”。行为未定义。任何事情都有可能发生。
  • 你自己回答了:未定义的行为意味着没有保证——无论你做出什么假设,它们都是错误的。没有正确的假设。
  • 可能的解释:用于分配 A 的内存来自一个大于 A 使用的 4 个字节的堆。

标签: c++ casting object-layout


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-12
      • 1970-01-01
      • 1970-01-01
      • 2015-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-01
      相关资源
      最近更新 更多