可通过铸造布局兼容的类型的一个访问私有成员函数?(Can one access private me

2019-07-30 10:58发布

从这个问题的讨论如何是引擎盖下用C ++实现私有变量的访问? 我提出的变化:而不是访问私有数据成员,可在一个通过铸造调用私有成员函数和依托布局兼容性?

某些代码(由Herb Sutter的列启发用途和使用权的滥用 )

#include <iostream>

class X 
{ 
public:
  X() : private_(1) { /*...*/ }

private: 
  int Value() { return private_; }
  int private_; 
};

// Nasty attempt to simulate the object layout
// (cross your fingers and toes).
//
class BaitAndSwitch
    // hopefully has the same data layout as X
{   // so we can pass him off as one
public:
  int Value() { return private_; }
private:
  int private_;
};

int f( X& x )
{
  // evil laughter here
  return (reinterpret_cast<BaitAndSwitch&>(x)).Value();
}

int main()
{
    X x;
    std::cout << f(x) << "\n"; // prints 0, not 1
    return 0;
}; 

注:该作品(至少在Ideone)! 是否有任何方式的新的C ++ 11标准给出了一个保证或至少一个实现定义的方式通过依赖于布局的兼容性和的reinterpret_cast /的static_cast绕过访问控制?

EDIT1:输出Ideone

EDIT2:在萨特的专栏中,他列出了两个原因为什么上面的代码是不能保证工作(尽管它在实践中的工作原理)

一)X和BaitAndSwitch的对象布局不能保证是相同的,但在实践中,他们可能永远会。

B)使用reinterpret_cast的结果是不确定的,但大多数编译器将让你尝试使用黑客希望的方式产生的参考值。

是否新的C ++标准11现在提供这些布局/ reinterpret_cast的保证?

Answer 1:

是的,你可以创建一个使用相同的布局,你想从窃取,然后类型的类型reinterpret_cast从类型到您的布局兼容的类型。 但是,这是由标准如果源目标类型均为标准布局类型只保护(当然,这只是实际工作,如果他们的布局是一样的)。 因此,如果源代码中有虚函数,你就完蛋了。

这似乎在这里同时满足萨特的问题。 标准布局的规则确保了两种类型的都是标准的布局定义以相同的顺序相同的部件是布局兼容(第9.2节,第17段):

两个标准的布局结构(第9节)类型是布局兼容如果它们具有相同数量的非静态数据成员和相应的非静态数据成员(在声明顺序)的具有布局兼容的类型(3.9)。

和用于规则reinterpret_cast指定两种标准布局类型(5.2.10节,第7段)之间的转换的含义是:

一个对象的指针可以被明确地转换为不同类型的对象的指针。 当型“指针T1”的prvalue v是转换为类型“指向cv T2”,其结果是static_cast<cv T2*>(static_cast<cv void*>(v)) ,如果T1和T2是标准-layout类型(3.9)和T2的对准要求并不比T1的严格,或者如果任一类型是无效的。



文章来源: Can one access private member functions through casting to layout-compatible types?