Virtual base classes size of

Tested on VS2012 Sp1

struct C{
virtual void f(){}
C(){}
};

struct C1:virtual C{
virtual void f(){}
virtual void f1(){}
C1(){} //commenting out the constructor gets the compiler to use 12 bytes (which is correct)
};


int main()
{
C1 d;
printf("%d ",sizeof(d));
return 0;
}

Why does this take 16 bytes

The reason why the sizeof operator is returning 16 for your C1 struct is derived from:

1) 4 bytes for pointer to your struct C due to virtual inheritance
2) 4 bytes for C1::f(), for pointer to function on vtable
3) 4 bytes for C1::f1(), again for pointer to function on vtable
4) 4 bytes for C1::C1() constructor again vtable pointer

You don't get anything for C::f() as you have hidden this due to C1::f()

Does that help?
so if I comment out C1(){} constructor for C1 , why do I get the correct 12 bytes.

Why do you keep saying "... the correct 12 bytes" ? The sizeof operator is returining the correct size for the argv you give it. If you take the C1 constructor out then you are getting 12 i.e. see my initial response and ignore the last 4 bytes i.e. (4). Don't forget that it will align along a 4 byte boundary.
using the compiler switch /dreportSingleClassLayoutC1:

1>  class C1	size(16):
1>  	+---
1>   0	| {vfptr}
1>   4	| {vbptr}
1>  	+---
1>  8	| (vtordisp for vbase C)
1>  	+--- (virtual base C)
1>  12	| {vfptr}
1>  	+---
1>  
1>  C1::$vftable@C1@:
1>  	| &C1_meta
1>  	|  0
1>   0	| &C1::f1
1>  
1>  C1::$vbtable@:
1>   0	| -4
1>   1	| 8 (C1d(C1+4)C)
1>  
1>  C1::$vftable@C@:
1>  	| -12
1>   0	| &(vtordisp) C1::f
1>  
1>  C1::f this adjustor: 12
1>  C1::f1 this adjustor: 0
1>  
1>  vbi:	   class  offset o.vbptr  o.vbte fVtorDisp
1>                 C      12       4       4 1


Without the constructor:
1>  class C1	size(12):
1>  	+---
1>   0	| {vfptr}
1>   4	| {vbptr}
1>  	+---
1>  	+--- (virtual base C)
1>   8	| {vfptr}
1>  	+---
1>  
1>  C1::$vftable@C1@:
1>  	| &C1_meta
1>  	|  0
1>   0	| &C1::f1
1>  
1>  C1::$vbtable@:
1>   0	| -4
1>   1	| 4 (C1d(C1+4)C)
1>  
1>  C1::$vftable@C@:
1>  	| -8
1>   0	| &C1::f
1>  
1>  C1::f this adjustor: 8
1>  C1::f1 this adjustor: 0
1>  
1>  vbi:	   class  offset o.vbptr  o.vbte fVtorDisp
1>                 C       8       4       4 0


http://www.openrce.org/articles/files/jangrayhood.pdf

//commenting out the constructor gets the compiler to use 12 bytes (which is correct)

The size is implementation defined. There is no 'correct' value.
thanks for the link,
what I dont understand is the additional 4 bytes when constructor code is added

the memory dumps shows the 4 Bytes to be initialized to 0 ( which means that there is no purpose for it)

Also if we dont add the constructor , the compiler will generate one for us (as shown in the dissassembly), but will not take up the additional 4 bytes (umm... why?)....
ms-help://MS.MSDNQTR.v90.en/dv_vccomp/html/93258964-14d7-4b1c-9cbc-d6f4d74eab69.htm

I have tried several combinations with and without #pragma vtordisp(on)
I get the same output except that with #pragma, I dont end up creating additional 4 bytes.

going by this the additional 4 bytes are not needed and may be created due to a feature provided in previous compiler (historical).
I get the same output except that with #pragma, I dont end up creating additional 4 bytes.

So, you get the same output... except that you don't.


going by this the additional 4 bytes are not needed and may be created due to a feature provided in previous compiler (historical).

Going by what? Clearly it is required when virtual functions may be called from a constructor in an inheritance hierarchy which includes virtual inheritance.
but these 4 bytes are always set to zero, what use are they...

I called the virtual functionof base/derived/most derived from base/derived/most derived (all combinations) with and without the #pragma, I get the same result except for the difference of 4 bytes

so what are these 4 bytes (set to zero) for?....
so what are these 4 bytes (set to zero) for?....

Who cares what value it's set to? Why is zero meaningless? Should we just get rid of 0 altogether? Who needs it?


I called the virtual functionof base/derived/most derived from base/derived/most derived (all combinations) with and without the #pragma, I get the same result except for the difference of 4 bytes

Are you familiar with what virtual inheritance is used for? If yes, then why do you think your example here is realistic? Even if it were realistic, one would presume this follows the same principle as undefined behavior. That is, sometimes the undefined behavior is (or seems to be) the expected behavior. That doesn't make it a good idea.
Last edited on
My best guess is that VS2012 does not need these 4 bytes , other compilers may need them and to create the same memory map, vs2012 adds these 4 bytes and sets them to zero

Since virtual base pointer is not available i.e. information on data slicing is not available, these 4 bytes may be used to keep this information hardcoded.
(need a different compiler to verify this).
In vs2012 ,(by debugging and watching the memory dump) virtual base pointer is initialized before any base constructor is called , hence data slicing inormation is available.
Last edited on
Topic archived. No new replies allowed.