浅谈借助指针突破C++类访问权限
有以下代码:
#include <iostream>
using namespace std;
class A {
public:
A(int a, int b, int c):m_a(a),m_b(b),m_c(c) {};
private:
int m_a;
int m_b;
int m_c;
};
int main() {
A obj(1, 2, 3);
int a = obj.m_a; //Compile Error
A* p = new A(5, 6, 7,);
int b= p->m_b; //Compile Error
return 0;
}
·上面代码编译不通过,由类的访问权限可知,private对象不可直接访问。但这只是语法层面的不可访问,我们仍然可通过指针访问到private和protected类成员。
·以上面obj对象来说,假设它的内存模型为
起始地址为0x1000,因为都为int整数类型,所以m_a、m_b、m_c都相距4个字节,所以起始地址+他们相距的字节数,就可以访问到成员变量的地址。
编译器就是以这种方式来取得变量的值。以上面代码为例:
假设m_b现在是公有类型
int b = p->m_b;//此时编译通过
此时编译器内部发生下面的转换:
int b = *(int*)( (int)p + sizeof(int) );
这段代码的含义:
·p 是对象 obj 的指针,
·(int)p
将指针转换为一个整数,这样才能进行加法运算;
·sizeof(int)
用来计算 m_b 的偏移;
·(int)p + sizeof(int)
得到的就是 m_b 的地址,不过因为此时是int
类型,所以还需要强制转换为int *
类型;
·开头的*
用来获取地址上的数据。
以此类推
那么上面两句编译错误的代码可改为
int a=*(int*)(&obj)
int b = *(int*)( (int)p + sizeof(int) );
/*-------访问变量m_c--------*/
int c =*(int*)( (int)p + sizeof(int)*2 );
这样就可以通过指针突破访问权限的设置。