C++ 面向对象的一大特性就是封装,使用不同的访问控制符来控制外接对其的访问权限。比如:

1 class A
2 {
3 public:
4 A(): i(10){}
5 void print(){ cout << "A::i = " << i << endl; }
6
7 private:
8 int i;
9 };

这里的A 类对象的 i 对外接来说就是透明的。通过private 来隐藏对象的某些属性。但是,C++也继承了大部分C的特性,比如说很好很强大的指针。利用指针,我们可以绕过编译器做一些 见不得光的事情。虽然不建议这么做,因为这样不仅破坏了数据的封装特性,也会带来很多危险。不过这里我还是这么做了。。。。。

请看下面的这个例子,利用指针p去修改 对象a 的私有成员i 的值:

#include <iostream>
using namespace std; class A
{
public:
A(): i(){}
void print(){ cout << "A::i = " << i << endl; } private:
const int i;
}; int main()
{
A a; int* p = (int*)&a; // 突破编译器的防线
a.print(); *p = ; // 偷偷修改a 对象私有成员的值
a.print(); return ;
}

执行结果:

A::i = 10
A::i = 30

通过打印结果可以看出p 真的做了不该做的事情

这时候有的朋友可能会觉得将A 类中的 i 声明成 const int 指针p应该就无能为力了吧。

事实证明 私有成员变量即使是 const 类型也是无济于事的,他们都无法阻挡指针的穿透力!

参考:http://www.cnblogs.com/CocoonFan/archive/2013/06/22/3149231.html

我们再来看看其他的方式。
 
1.伪造者方式
这个伎俩是现将某个有待伪造的类定义复制一份,然后通过该复制后的“赝品”来达到目的,且看
void Hijack(X &x)
{
x.m_nPrivate = 2;
} class X
{
// 手工添加
friend ::Hijack(X &); // 这里是复制X类定义
private:
int m_nPrivate; public:
X()
: m_nPrivate(1)
{} template<typename T>
void Func(const T &t)
{} const int GetValue()
{
return m_nPrivate;
}
};
这个伎俩被VC2008的编译器逮住了,没有编译通过。因为他违反了唯一定义规则(ODR,One Definition Rule)。看来语言律师还是不会放过这种没脑子的造假者!打假、打假,越打越假!
 
2. 偷窃者方式
偷偷的改变定义类的含义。且看:
#define private public    // 万恶的宏伎俩啊

void Hijack(X &x)
{
x.m_nPrivate = 2;
}

他的两根手指头很灵活哟。在VC2008成功执行得到。然而他却有两个违背标准的行为:

1)#define 保留字是非法的

2)违反了但一定以规则(ODR),然而类的底层内存布局没改变,故可行

3.骗子方式

// 同X的内存布局,只有一个int型的变量
class BaitSwitch
{
public:
int m_nNotPrivate;
}; void Func(X &x)
{
(reinterpret_cast(x)).m_nNotPrivate = 2;
}
在VC2008上成功运行达到目的,但是却有漏洞:
标准中reinterpret_cast的行为未定义,VC2008允许返回的结果引用。所以也成功让骗子得逞。
 
4.语言律师方式
律师就是钻法律的漏洞,永远也不会被逮住,他是在钻法律的空子!且看
namespace
{
struct Y{};
} template<>
void X::Func(const Y&)
{
m_nPrivate = 2;
} void Test()
{
X x;
cout << x.GetValue() << endl; x.Func(Y());
cout << x.GetValue() << endl;
}
他能成功主要是利用了X具有一个成员模板的事实,代码完全符合标准,标准也确保这种行为会按照编码者的意图行事。boost和loki中大量运用此手法。
 
看法:
我相信这并不是C++访问控制机制的漏洞,或许,我们本不应该这样做。用成员模板提供一种有效的访问似有成员数据可以绕过累的访问控制,这也许就是我们想达到的目的。 

C++利用指针突破私有成员访问限制的更多相关文章

  1. [转载] C++ 突破私有成员访问限制

    最后一个方式 模板尚未弄清楚. 我们在写代码的时候,按约定都是把成员数据放到private访问区中,然后在通过相应的函数来存取.那又有什么样的代码可以突破访问权限来直接操作类中private区段中的成 ...

  2. 利用指针突破C++编译器的防线

    C++ 面向对象的一大特性就是封装,使用不同的访问控制符来控制外接对其的访问权限.比如: class A { public: A(): i(){} void print(){ cout << ...

  3. C++ //继承中的对象模型 //利用开发人员命令提示工具查看对象模型 //父类中所有非静态成员属性都会被 子类继承下去 //父类中私有成员属性 是被编译器给隐藏了 因此是访问不到 但是确实被继承下去了

    1 //继承方式 2 //语法:class 子类 :继承方式 父类 3 //继承方式 三种: 4 //1.公共继承 5 //2.保护继承 6 //3.私有继承 7 8 /* 9 #include &l ...

  4. 使用C#反射机制访问类的私有成员【转】

    首先我必须承认访问一个类的私有成员不是什么好做法.大家也都知道私有成员在外部是不能被访问的.而一个类中会存在很多私有成员:如私有字段.私有属性.私有方法.对于私有成员访问,可以套用下面这种非常好的方式 ...

  5. C#中访问私有成员--反射

    首先我必须承认访问一个类的私有成员不是什么好做法.大家也都知道私有成员在外部是不能被访问的.而一个类中会存在很多私有成员:如私有字段.私有属性.私有方法.对于私有成员访问,可以套用下面这种非常好的方式 ...

  6. 通过指针访问C++对象的私有成员

    C++对象的私有成员是禁止类外的访问的.但是我们仍然可以通过指针访问C++对象的私有成员. #include <iostream> using namespace std; class A ...

  7. CPP-基础:关于私有成员的访问

    a.C++的类的成员函数中,允许直接访问该类的对象的私有成员变量. b.在类的成员函数中可以访问同类型实例的私有变量. c.拷贝构造函数里,可以直接访问另外一个同类对象(引用)的私有成员. d.类的成 ...

  8. java中用反射访问私有方法和私有成员[转]

    转自: http://zhouyangchenrui.iteye.com/blog/470521 java的反射可以绕过访问权限,访问到类的私有方法和成员.可能这点会引起安全性的讨论.反射的使用帮助解 ...

  9. VC6.0中友元函数无法访问类私有成员的解决办法

    举个例子: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #inclu ...

随机推荐

  1. Bitmap 与ImageSource之间的转换

    public class ImageConverter { [DllImport("gdi32.dll", SetLastError = true)] private static ...

  2. Ubuntu14.0.4 64位安装ADT问题

    将ADT 解压之后,新建Android工程后没有R文件: google之后说要安装 ia32-libs 提示如下: 安装lib32z1 安装完成后,再次新建工程,报错如下: 编译存在问题:则继续安装以 ...

  3. android gridview布局,实现长按某一个,所有项都显示删除的图标

    最近一直忙着项目开发,有段时间没有写博文了,今天想跟大家分享的是长按gridview中的某一项显示删除图标,此时点击某项便可删除,再长按取消删除图标. gridview的布局文件如下: <?xm ...

  4. zhihu spark集群,书籍,论文

    spark集群中的节点可以只处理自身独立数据库里的数据,然后汇总吗? 修改 我将spark搭建在两台机器上,其中一台既是master又是slave,另一台是slave,两台机器上均装有独立的mongo ...

  5. PHP代码,拒绝频繁访问

    一个网站性能有限,如果有人恶意去频繁对页面进行刷新,其实对服务器影响是很大的,导致资源使用非常高,直接影响到其他用户的体验. 那么对于这样的一些频繁访问,我们该如何去拒绝它呢? 我总结了两种方法:第一 ...

  6. iphone 6s pp助手 越狱

    https://www.apple.com/iphone-6/合适初高中学习英语http://www.travelchinaguide.comhttp://jailbreak.25pp.com/ ip ...

  7. ssl相关

    http://www.willrey.com/support/ssl_DES.html http://www.07net01.com/linux/Linuxdejiamirenzhenggongnen ...

  8. 【转】Android LCD(四):LCD驱动调试篇

    关键词:android LCD TFTSN75LVDS83B  TTL-LVDS LCD电压背光电压 平台信息:内核:linux2.6/linux3.0系统:android/android4.0 平台 ...

  9. eclipse中误删了servers文件

    Eclipse中误删了servers文件,需要重新添加tomcat服务器,这时就会遇到在New Server对话框中选择了Tomcat 6/7后却无法单击"Next"按钮的问题,如 ...

  10. jQuery.extend()、jQuery.fn.extend()扩展方法示例详解

    jQuery自定义了jQuery.extend()和jQuery.fn.extend()方法.其中jQuery.extend()方法能够创建全局函数或者选择器,而jQuery.fn.extend()方 ...