[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 260
  • Last Modified:

pointer to member function difference ?

I have the following typdef :

typedef void (CCommandes::*LPFSMFUNC)(WORD idx, struct ParamQueue *pParam);

and the following line of code :

size_t typelen = sizeof( LPFSMFUNC );

The value of typelen is always "16" ...

Why not 4 ?

I try that code on 2 different machines ...


I have also :

LPFSMFUNC TabFunc ( 64 );

In MS VC 6.0 debugger Watch windows I can see :

TabFunc
 -[0]
.
.
.
 -[255] !!!


BOOL CGroupe::AddFunc (UINT key, LPFSMFUNC pfunc)
{
      if ((TabFunc[key] != NULL) || (key>MAXNFUNC))
            return FALSE;

      DWORD typelen = sizeof( LPFSMFUNC );
      TabFunc[key]=pfunc;
      return TRUE;
}

If key = 1 for example, in Watch window I can see:

TabFunc
 -[0] 0x00000000

 -[1] 0x00000000

 -[2] 0x00000000

 -[3] 0x00000000

 -[4] 0x004014ec CCommandes::GrpPrintShop_MPGetUser(WORD wThreadIdxParam, struct ParamQueue * pParam)

....


I know there is something wrong but I can't see what .

Thanks for helping me .


0
bletual
Asked:
bletual
1 Solution
 
ZoppoCommented:
listening...

BTW, what happens when you change byte alignment options of your compiler (if possible)

ZOPPO
0
 
bletualAuthor Commented:
Byte alignment to 1, 2, 4, 8 or 16 bytes didn't change
the result .



0
 
jkrCommented:
Well, I assume that the size also depends on the parameter list...
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
Todd_LindbergCommented:
Could you show us the class declaration for CCommandes?  Does that class have multiple inheritance?
0
 
bletualAuthor Commented:
No,

the size do not depend on the parameter list

typedef void (CCommandes::*LPFSMFUNC2)(WORD idx, struct ParamQueue *pParam, struct ParamQueue *pParam2);

sizeof ( LPFSMFUNC2 ) return 16 also ...



0
 
bletualAuthor Commented:
class CCommandes
{
public:
      CCommandes();

      // pParam->lpszPar[1]      Enter Date.
      // pParam->lpszPar[2]      Enter Time.

      // pParam->dwPar[0]            Full ID.
      // pParam->dwPar[1]            Pod Score.
      // pParam->dwPar[2]            Debriefing Score.
      // pParam->dwPar[3]            Minutes in Labyrinth.

      // pParam->iPar[0]            Nb of challenges.
      // pParam->iPar[1]            Nb of temples visited.
      // pParam->iPar[2]            Nb of correctly answered DB questions.
      // pParam->iPar[3]            Level of Debriefing questions (0-4).

      DWORD      m_dwFullID;
      char      m_Name[128];
      char      m_Firstname[128];
      char      m_Add1[128];
      char      m_Add2[128];
      char      m_City[128];
      char      m_State[128];
      char      m_Country[128];
      char      m_Zip[128];
      char      m_Email[128];
      char      m_Gender[128];
      DWORD      m_Age;
      char      m_Language[128];
      char      m_LastVisit[128];
      char      m_Friends[128];
      char      m_strDate[128];      
      char      m_strTime[128];
      char      m_strEndDate[128];
      char      m_strEndTime[128];
      char      m_strDbDate[128];            
      char      m_strDbTime[128];
      DWORD      m_nbPods;
      DWORD      m_PodScore;
      DWORD      m_DbScore;
      DWORD      m_DbLevel;                        ;

      char      m_strPodHisto[1024];
      char      m_strDebriefHisto[1024];

      // Recoit une commande "start"
      void CCommandes::GrpPrintShop_MPGetUser(WORD wThreadIdxParam, struct ParamQueue * pParam);
      void CCommandes::GrpPrintShop_MPGetHistory(WORD wThreadIdxParam, struct ParamQueue * pParam);
      void CCommandes::GrpPrintShop_PMGetUser(DWORD id);
      void CCommandes::GrpPrintShop_PMGetHistory(DWORD id);
      void CCommandes::GrpPrintShop_PMSetUser(char * lpszName, char * lpszFirstName,       char * lpszAdd1, char * lpszAdd2,
                                                                  char * lpszCity, char * lpszState,      char * lpszCountry, char * lpszZip,
                                                                  char * lpszEmail, char * lpszGender, char * lpszFriends, DWORD dwId,
                                                                  DWORD dwLanguage, DWORD dwAge);
      void CCommandes::GrpPrintShop_PMGetUserById(DWORD Fullid);
      void CCommandes::GrpPrintShop_MPStart(WORD wThreadIdxParam, struct ParamQueue * pParam);
};
0
 
Todd_LindbergCommented:
Well that blows my theory.  I figured you probably had some multiple inheritance scheme, which makes the compiler store a pointer to the function and an offset so it can adjust the this pointer to point to an inherited base class.

I cut-and-pasted your class and compiled it here (Visual Studio 6.0 SP3), and I got 4 for my value of typelen.

If I do this:

class CFoo {};
Class CGoo {};
class CCommandes : public CGoo, public CFoo {
};

Then the value of typelen increases to 8.



0
 
Todd_LindbergCommented:
VOILA!!!

Under Compiler Settings / Pointer-to-member representation, are you using "General Purpose Always"?

When I changed that, by typelen jumped to 16, just like yours.



Change that setting to "Best Case Always" and this might solve your problem.
0
 
bletualAuthor Commented:
You show me the right way to heaven !

But the facts are :

If "Best Case Always"
 typelen = 16 .

If "General Purpose Always"
    "Point to Any Class *"
 typelen = 16 .
 
If "General Purpose Always"
    "Point to Single- and Multiple-Inheritance Classes"
 typelen = 8 .
   
If "General Purpose Always"
    "Point to Single- and Multiple-Inheritance Classes"
 typelen = 4 .

Do you have some explanations ?


     
0
 
Todd_LindbergCommented:
I don't know the exact internal representation of how MSC++ does multiple inheritance, but it has something to do with storing offsets to the individual base classes of multiple inheritance.

For "General Purpose Always", the representation must assume that all classes use the worst-case representation that needs several offsets.  Probably for your simple class, all the offsets are always zero.

Now for your debugging example where it showed 256 elements in that function array, I have a feeling the Debugger doesn't handle that function array correctly -- it probably assumes (like most of us do) the function array is only an array of pointers, rather than a compilicated array of pointers and offsets.  So it thinks those offsets are extra elements in the array.


P.S. In your last comment, are the typelen values you indicate backwards?  I would think the "Best Case Always" would have a len=4 and "General Purpose Always" have a len=16.



0
 
bletualAuthor Commented:
If "Best Case Always"  typelen = 16 .

 If "General Purpose Always"
 "Point to Any Class *"
  typelen = 16 .
                                       
 If "General Purpose Always"
 "Point to Single- and Multiple-Inheritance Classes"
  typelen = 8 .
                                         
 If "General Purpose Always"
 "Point to Single- and Multiple-Inheritance Classes"
   typelen = 4 .



For me, the only case where typelen = 4 is the last one.

0

Featured Post

The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now