V
Vladimir_petter
Hello All,
I've fount that if I compile the same program using gcc and vc 2003 the same class E (see complete source bellow) has different size (on vc it is 4 bytes bigger). Digging into this I've found that vc is reserving a dword in the E class right before storage for virtual base class. In my tests value of this dword always was 0. I did not see any code referencing this memory.
Anybody has any idea what this dword is for?
Vladimir.
/*
Compile:
cl -EHsc -Zi t11.cpp
Classes hierarchy
A
/ \
| |
| |
B D C
| | |
| | |
\ | /
E
Output: My Interpritation:
ma=ff1, sizeof(A)=8 sizeof(vtable) + sizeof(ma_)
mb=ff2, sizeof(B)=20 sizeof(vtable) + sizeof(mb_) + 1*sizeof(DWORD) + sizeof(A)
mc=ff3, sizeof(C)=20 sizeof(vtable) + sizeof(mb_) + 1*sizeof(DWORD) + sizeof(A)
md=ff4, sizeof(D)=8 sizeof(vtable) + sizeof(md_)
me=ff5, sizeof(E)=40
&before - &after = 13
Layout of the stack in the "main" function:
Nr Address Value Points to My Interpritation
01 0012feb0 00000fe2 << veriable "after"
02 0012feb4 0041f178 t11!E::`vftable' << veriable e, start of E, start of E:
03 0012feb8 00000ff4 << e.md_
04 0012febc 0041f188 t11!E::`vbtable' << start of E::B
05 0012fec0 00000ff2 << e.mb_
06 0012fec4 0041f17c t11!E::`vbtable' << start of E::C
07 0012fec8 00000ff3 << e.mc_
08 0012fecc 00000ff5 << e.me_
09 0012fed0 00000000 << ???WHAT ARE THIS FOR???
10 0012fed4 0041f174 t11!E::`vftable' << start of E::A
11 0012fed8 00000ff1 << e.ma_, end of E
12 0012fedc 0000000c << veriable "distance"
13 0012fee0 00000fe1 << veriable "before"
*/
#include<iostream>
using namespace std;
class A {
public:
explicit A(long ma)
: ma_(ma) {
}
virtual void foo();
private:
long ma_;
};
void A::foo() {
cout << hex << "ma=" << ma_ << ", sizeof(A)=" << dec << sizeof(A) << "\n";
}
class B : public virtual A {
public:
explicit B(long mb)
: mb_(mb), A(0) {
}
virtual void foo();
private:
long mb_;
};
void B::foo() {
cout << hex << "mb=" << mb_ << ", sizeof(B)=" << dec << sizeof(B) << "\n";
}
class C : public virtual A {
public:
explicit C(long mc)
: mc_(mc), A(0) {
}
virtual void foo();
private:
long mc_;
};
void C::foo() {
cout << hex << "mc=" << mc_ << ", sizeof(C)=" << dec << sizeof(C) << "\n";
}
class D {
public:
explicit D(long md)
: md_(md) {
}
virtual void foo();
private:
long md_;
};
void D::foo() {
cout << hex << "md=" << md_ << ", sizeof(D)=" << dec << sizeof(D) << "\n";
}
class E : public B, public C, public D {
public:
explicit E(long ma=0xFF1, long mb=0xFF2, long mc=0xFF3, long md=0xFF4, long me=0xFF5)
: A(ma), B(mb), C(mc), D(md), me_(me) {
}
virtual void foo();
private:
long me_;
};
void E::foo() {
A::foo();
B::foo();
C::foo();
D::foo();
cout << hex << "me=" << me_ << ", sizeof(E)=" << dec << sizeof(E) << "\n";
}
int main(int, char **) {
cout << hex;
int distance = 0;
int before = 0xFE1;
E e;
if(!distance) { //to prevent compiler from rearanging veriables on the stack
int after = 0xFE2;
distance = &before - &after;
}
e.foo();
cout << dec << "&before - &after = " << abs(distance) << "\n";
return 0;
}
I've fount that if I compile the same program using gcc and vc 2003 the same class E (see complete source bellow) has different size (on vc it is 4 bytes bigger). Digging into this I've found that vc is reserving a dword in the E class right before storage for virtual base class. In my tests value of this dword always was 0. I did not see any code referencing this memory.
Anybody has any idea what this dword is for?
Vladimir.
/*
Compile:
cl -EHsc -Zi t11.cpp
Classes hierarchy
A
/ \
| |
| |
B D C
| | |
| | |
\ | /
E
Output: My Interpritation:
ma=ff1, sizeof(A)=8 sizeof(vtable) + sizeof(ma_)
mb=ff2, sizeof(B)=20 sizeof(vtable) + sizeof(mb_) + 1*sizeof(DWORD) + sizeof(A)
mc=ff3, sizeof(C)=20 sizeof(vtable) + sizeof(mb_) + 1*sizeof(DWORD) + sizeof(A)
md=ff4, sizeof(D)=8 sizeof(vtable) + sizeof(md_)
me=ff5, sizeof(E)=40
&before - &after = 13
Layout of the stack in the "main" function:
Nr Address Value Points to My Interpritation
01 0012feb0 00000fe2 << veriable "after"
02 0012feb4 0041f178 t11!E::`vftable' << veriable e, start of E, start of E:
03 0012feb8 00000ff4 << e.md_
04 0012febc 0041f188 t11!E::`vbtable' << start of E::B
05 0012fec0 00000ff2 << e.mb_
06 0012fec4 0041f17c t11!E::`vbtable' << start of E::C
07 0012fec8 00000ff3 << e.mc_
08 0012fecc 00000ff5 << e.me_
09 0012fed0 00000000 << ???WHAT ARE THIS FOR???
10 0012fed4 0041f174 t11!E::`vftable' << start of E::A
11 0012fed8 00000ff1 << e.ma_, end of E
12 0012fedc 0000000c << veriable "distance"
13 0012fee0 00000fe1 << veriable "before"
*/
#include<iostream>
using namespace std;
class A {
public:
explicit A(long ma)
: ma_(ma) {
}
virtual void foo();
private:
long ma_;
};
void A::foo() {
cout << hex << "ma=" << ma_ << ", sizeof(A)=" << dec << sizeof(A) << "\n";
}
class B : public virtual A {
public:
explicit B(long mb)
: mb_(mb), A(0) {
}
virtual void foo();
private:
long mb_;
};
void B::foo() {
cout << hex << "mb=" << mb_ << ", sizeof(B)=" << dec << sizeof(B) << "\n";
}
class C : public virtual A {
public:
explicit C(long mc)
: mc_(mc), A(0) {
}
virtual void foo();
private:
long mc_;
};
void C::foo() {
cout << hex << "mc=" << mc_ << ", sizeof(C)=" << dec << sizeof(C) << "\n";
}
class D {
public:
explicit D(long md)
: md_(md) {
}
virtual void foo();
private:
long md_;
};
void D::foo() {
cout << hex << "md=" << md_ << ", sizeof(D)=" << dec << sizeof(D) << "\n";
}
class E : public B, public C, public D {
public:
explicit E(long ma=0xFF1, long mb=0xFF2, long mc=0xFF3, long md=0xFF4, long me=0xFF5)
: A(ma), B(mb), C(mc), D(md), me_(me) {
}
virtual void foo();
private:
long me_;
};
void E::foo() {
A::foo();
B::foo();
C::foo();
D::foo();
cout << hex << "me=" << me_ << ", sizeof(E)=" << dec << sizeof(E) << "\n";
}
int main(int, char **) {
cout << hex;
int distance = 0;
int before = 0xFE1;
E e;
if(!distance) { //to prevent compiler from rearanging veriables on the stack
int after = 0xFE2;
distance = &before - &after;
}
e.foo();
cout << dec << "&before - &after = " << abs(distance) << "\n";
return 0;
}