可以通过转换为布局兼容类型来访问私有成员函数吗? [英] Can one access private member functions through casting to layout-compatible types?

查看:27
本文介绍了可以通过转换为布局兼容类型来访问私有成员函数吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从这个问题的讨论 在 C++ 中如何访问私有变量在幕后实现?我提出了一个变体: 除了访问私有数据成员之外,是否可以通过强制转换和依赖布局兼容性来调用私有成员函数?

From the discussion of this question How is access for private variables implemented in C++ under the hood? I posed a variation: instead of accessing a private data member, can one call private member functions through casting and relying on layout-compatibility?

一些代码(灵感来自 Herb Sutter 的专栏 访问权限的使用和滥用)

Some code (inspired by Herb Sutter's column Uses and Abuses of Access Rights )

#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) << "
"; // prints 0, not 1
    return 0;
}; 

注意:这有效(至少在 Ideone 上)!有没有新的C++11标准提供了一种保证或至少一种实现定义的方法来通过依赖布局兼容性和reinterpret_cast/static_cast来规避访问控制?

Note: this works (at least on Ideone)! Is there any way the new C++11 Standard gives a guaranteed or at least an implementation-defined way to circumvent the access control by relying on layout-compatibility and reinterpret_cast / static_cast?

EDIT1:在 Ideone

EDIT2:在 Sutter 的专栏中,他列出了上述代码不能保证有效的两个原因(尽管它在实践中有效)

EDIT2: In Sutter's column he lists two reasons why the above code is not guaranteed to work (although it works in practice)

a) X 和 BaitAndSwitch 的对象布局不保证是相同,尽管在实践中它们可能总是如此.

a) The object layouts of X and BaitAndSwitch are not guaranteed to be the same, although in practice they probably always will be.

b) reinterpret_cast 的结果是未定义的,尽管大多数编译器会让你尝试以这种方式使用结果引用黑客有意.

b) The results of the reinterpret_cast are undefined, although most compilers will let you try to use the resulting reference in the way the hacker intended.

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

Does the new C++11 Standard now provide these layout / reinterpret_cast guarantees?

推荐答案

是的,您可以创建一个使用与您试图从中窃取的类型相同的布局的类型,然后 reinterpret_cast 从该类型与您的布局兼容类型.但这仅在源和目标类型都是标准布局类型时才受标准保护(当然,只有在它们的布局相同时才真正起作用).所以如果源有虚函数,你就完蛋了.

Yes, you could create a type that uses the same layout as the type you're trying to pilfer from, then reinterpret_cast from that type to your layout compatible type. But this is only protected by the standard if both the source and destination types are standard layout types (and of course, it only actually works if their layouts are the same). So if the source has virtual functions, you're screwed.

这似乎满足了 Sutter 的两个问题.标准布局规则确保以相同顺序定义相同成员的两种标准布局类型是布局兼容的(第 9.2 节,第 17 段):

This seems to satisfy both of Sutter's issues here. The rules of standard layout ensure that two types that are both standard layout that define the same members in the same order are layout-compatible (section 9.2, paragraph 17):

如果两个标准布局结构(第 9 条)类型具有相同数量的非静态数据成员并且相应的非静态数据成员(按声明顺序)具有布局兼容类型 (3.9),则它们是布局兼容的.

Two standard-layout struct (Clause 9) types are layout-compatible if they have the same number of non-static data members and corresponding non-static data members (in declaration order) have layout-compatible types (3.9).

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

And the rules for reinterpret_cast specify the meaning of the conversion between two standard layout types (section 5.2.10, paragraph 7):

对象指针可以显式转换为不同类型的对象指针.当类型为指向 T1 的指针"的纯右值 v 转换为类型指向 cv T2 的指针"时,结果为 static_cast(static_cast(v)) 如果 T1 和 T2 都是标准布局类型 (3.9) 并且 T2 的对齐要求不比 T1 严格,或者如果任一类型为 void.

An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue v of type "pointer to T1" is converted to the type "pointer to cv T2", the result is static_cast<cv T2*>(static_cast<cv void*>(v)) if both T1 and T2 are standard-layout types (3.9) and the alignment requirements of T2 are no stricter than those of T1, or if either type is void.

这篇关于可以通过转换为布局兼容类型来访问私有成员函数吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆