开发者

How to access private data private member through its offset?

开发者 https://www.devze.com 2023-04-01 22:54 出处:网络
I\'m trying开发者_开发技巧 to access and modify the private data member of a class by offset. AFAIK, first thing is to calculate the offset, then access the member through the offset.

I'm trying开发者_开发技巧 to access and modify the private data member of a class by offset.

AFAIK, first thing is to calculate the offset, then access the member through the offset.

Here is my code.

class Test {  
public:
    int a;  
    int b;
private:  
    int c;
};  
Test test;
cout << *(&test + &Test::b + 1);  // access c

I got an error : "+" operator invalid, the right operand contains "int Test::*" type.

There is a similar post, it printf the offset of abas 1,4, but when try like this:

cout << &Test::a << '\t' << &Test::b;  

I got 1 1.

My question:

1. Why cout got the wrong result?

2. What does Test::*p point to?

3. How to access and modify the Test::* pointer?(Or how to access the private member when doesn't know the offset?)


This works:

#include <iostream>
using namespace std;
class test {
  public:
      int a;
      int b;
      test () : c(100) {}
      void show () {cout << "c = " << c << endl;}
  private:
      int c;
};


int main (void)
{
  test x;
  test *ptr;
  ptr = &x;
  ptr++;
  ptr = (test *) ((int *)ptr - 1);
  cout << "c = " << *((int *)ptr) << endl;
  *((int *)ptr) = 200;
  x.show ();
  return 0;
}

But the offset should be known. In the above ptr is type of test and therefore ptr++ will increment the pointer value to sizeof (test). Because the location of the private member c is at the end and is a type of integer so one integer step is decreased by casting ptr into int * first and then decrementing 1, which now points to the address of c. It is printed first, and next the value of c is modified by first casting ptr to int * and then assigning a value, and then printed.

It is not guaranteed that it will always get the value of c when you know the position of c as the padding might be different in other cases. Also there is no point accessing a private data member because at the time of the object design approach it was made to be accessed by the member functions and is a tool for organization by providing abstraction. When implementing such a concept in other languages like C, which does not have object oriented features, you can implement such a private - public environment by personally following a convention, but the compiler will not enforce anything if you accessed a "private" where you actually shouldn't. But in C++ the compiler provides the restriction and stops you from diverting and breaking the object orientated design which you made. At run time all's in memory and you can access them without any restriction from your code at that time nothings private or public. If you know how to interpret the bytes in the executable you can change anything you like, even the code itself. I do not think this is a good idea to be implemented, as it will make the code unpredictable and unportable and definitely violate the OOD approach.


Test::p is a member pointer. Member pointers are not the same a regular pointers. You can't just do pointer arithmetic to them. They are not references to a location in memory; they're a special kind of object.

If you want a regular pointer to an object (ie: the member of an existing class), you have to get the pointer to that particular piece of memory.

&test.b

BTW, whatever private data you're trying to access was made private for a reason. So unless you have a very, very good reason to basically break memory protection (as well as portability, since this is completely undefined behavior), you should not do this.


If you must, the #define private public trick should do it.


You really cannot test for the memory layout of the objects. The compiler is free to do it as it sees fit.

When the members are separated by different access specifiers, the language doesn't say anything about their order. In your case, a must be followed by b but in theory c can be placed wherever the compiler sees fit.

In a larger example like

class Test {  
public:
    int a;  
    int b;
private:  
    int c;
protected:
    double d;
};

the compiler is allowed to place d before c if that would improve alignment, for example.


*((int*) &test + 2);    

With this, you should be able to access the private member c. Try it in gdb online compiler or add header cstdlib.

Now let me show you how to access any members of a class using pointer arithmetic other than the member functions.

Consider the following code:

    #include <iostream>        
#include <cstring>        

using namespace std;        

class test        
{        
    public:        
    int a;        
    char name[50];        
    double m;        
};        

int main()        
{        
    test *t = new test;        

    void *ptr = (char*)t + offsetof(test, m);         
    void *ptr1 = (char*)t + offsetof(test, name);        

    //printf("%p\n%p\n", &t->name, ptr1);        
    *((double*)ptr) = 98.999006;        
    strcpy((char*)ptr1,"Pointer Arithmetic");        

    cout<<t->m<<endl;        
    cout<<t->name<<endl;       

    cout<<(*(double*)ptr)<<endl<<((char*)ptr1)<<endl;    
    cout<<*((double*)((char*)t + offsetof(test, m)))<<endl;    
    cout<<(char*)t + offsetof(test, name);    
 }        

Output: 98.999
Pointer Arithmetic
98.999
Pointer Arithmetic
98.999
Pointer Arithmetic

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号