May 21, 2013

[C++][NOTE][ORIGINAL] Pointer to member function dive

Pointer to member function is really an interesting thing.

Here's the code to observe how pointer-to-member-function structure's offset works.



With the observation, when marking out the data member in class B, the offset of pointer-to-member-function of class D will be 0.

I assume the compiler did some work by rearranged the inheritance order to :
class D : public B, public A
in order to save cycles from doing "this" pointer adjustment.

code is compiled under g++ 4.7.2 with -Wpmf-conversions enabled.

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

class A{
public:
   unsigned long long a[7];

   void ha_a() { cout << "ha_a" << endl; }
};

class B{
public:
   int a; //Mark out will cause thunk offset to be 0 ,i.e, the LowerPtr will be nil
   void ha_b() { cout << "ha_b" << endl; }
};

class D: public A, public B{
};


typedef void (B::* mfuncPtrB)();
typedef void (D::* mfuncPtrD)();
typedef void (* funcPtrD)(D*);
mfuncPtrD   mfp_D = &D::ha_b;
mfuncPtrB   mfp_B = &B::ha_b;
funcPtrD     fp_D  = (funcPtrD)(&D::ha_b);

char P[16]; //initial to null

int main(){
   
   // sizeof pointer to member function
   cout << "sizeof(mfuncPtr) : " << sizeof(mfuncPtrD) << endl;
   // sizeof pointer to function
   cout << "sizeof(funcPtr) : " << sizeof(funcPtrD) << endl;
   
   reinterpret_cast <mfuncPtrD&> (P) = mfp_D;

   char UpperPtr[8];
   char LowerPtr[8];
   strncpy(UpperPtr, P, 8);
   strncpy(LowerPtr, P+8 , 8);

   printf("UpperPtr : %p\n", *UpperPtr );
   printf("LowerPtr : %p\n", *LowerPtr );
   //printf("%016X\n", *UpperPtr );
   //printf("%016X\n", *LowerPtr );

   D dobj;
   funcPtrD fpd = (funcPtrD)(dobj.*mfp_D);
   fpd(&dobj);

   
   printf("Address of member function ha_b : %p\n", *fpd );
   printf("Address of member function ha_b : %p\n", &B::ha_b );
}


Output:

sizeof(mfuncPtr) : 16
sizeof(funcPtr) : 8
UpperPtr : 0x7e
LowerPtr : 0x38
ha_b
Address of member function ha_b : 0x400c7e
Address of member function ha_b : 0x400c7e


Reference:
Pointers to member functions are very strange animals
C++ Tips: Adjustor thunk: what is it, why and how it works
pointers to member functions with multiple inheritance
6.7 Extracting the function pointer from a bound pointer to member function
What is a 'thunk'?

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.