On 6 December 2011 20:59, Bruce Fraser wrote: > The following code was compiled with g++ 4.1.2 and again with g++ > 4.6.2 on 64-bit Linux (more details at the end). Note that S1 and S3 > have identical data members. S1 has a constructor defined, S3 does > not. S2 inherits from S1 and S4 inherits from S2. The size and > layout SHOULD be the same, but it is not as you can see from the > output. For C++98 / C++03 there are no guarantees about class layout except for POD types, and the presence of base classes and user-defined constructors prevents your types being PODs. C++11 provides the more fine-grained concept of a standard-layout struct, but even then I don't think there's any guarantee your S2 and S4 will have the same layout. If I comment out the constructor, and uncomment the > operator== function, the alignment becomes the same for both classes. > While no specific defect results in the code, this unpredictable > behaviour makes it impossible to match the ABI of the OSF1 platform > that we are porting away from and there are an enormous number of > binary data files that we would like to read. > > Any insight? I’m very experienced with C++, but not quite a guru of > the highest order. This looks like a defect to me. > > <code> > #include <iostream> > > using namespace std; > > struct S1 { > long a; > char b; > S1(){ a = 1; b = 2; }; > // bool operator==( const S1& c ) { return a==c.a && b==c.b; }; > }; > > struct S2 : public S1 { > char a; > }; > > struct S3 { > long a; > char b; > bool operator==( const S1& c ) { return a==c.a && b==c.b; }; > }; > > struct S4 : public S3 { > char a; > }; > > int main() { > S1 s1; > S2 s2; > S3 s3; > S4 s4; > > cout << "Size of S1 is " << sizeof( S1 ) << endl; > cout << "Offset of a is " << (int)((char*)&s1.a - (char*)&s1) > << endl << endl; > > cout << "Size of S2 is " << sizeof( S2 ) << endl; > cout << "Offset of a is " << (int)((char*)&s2.a - (char*)&s2) > << endl << endl; > > cout << "Size of S3 is " << sizeof( S3 ) << endl; > cout << "Offset of a is " << (int)((char*)&s3.a - (char*)&s3) > << endl << endl; > > cout << "Size of S4 is " << sizeof( S4 ) << endl; > cout << "Offset of a is " << (int)((char*)&s4.a - (char*)&s4) > << endl << endl; > > return(0); > } > </code> > > <output> >> g++ struct_align.cpp -Wall -Wextra -o struct_align.exe >> ./struct_align.exe > Size of S1 is 16 > Offset of a is 0 > > Size of S2 is 16 > Offset of a is 9 > > Size of S3 is 16 > Offset of a is 0 > > Size of S4 is 24 > Offset of a is 16 > </output> > >> uname -a > Linux riffraff 2.6.18-274.el5 #1 SMP Fri Jul 8 17:36:59 EDT 2011 > x86_64 x86_64 x86_64 GNU/Linux > >> /usr/bin/g++ -v > Using built-in specs. > Target: x86_64-redhat-linux > Configured with: ../configure --prefix=/usr --mandir=/usr/share/man > --infodir=/usr/share/info --enable-shared --enable-threads=posix > --enable-checking=release --with-system-zlib --enable-__cxa_atexit > --disable-libunwind-exceptions --enable-libgcj-multifile > --enable-languages=c,c++,objc,obj-c++,java,fortran,ada > --enable-java-awt=gtk --disable-dssi --disable-plugin > --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre > --with-cpu=generic --host=x86_64-redhat-linux > Thread model: posix > gcc version 4.1.2 20080704 (Red Hat 4.1.2-51) > >> /usr/local/bin/g++ -v > Using built-in specs. > COLLECT_GCC=/usr/local/bin/g++ > COLLECT_LTO_WRAPPER=/usr/local/gcc-4.6.2/libexec/gcc/x86_64-unknown-linux-gnu/4.6.2/lto-wrapper > Target: x86_64-unknown-linux-gnu > Configured with: ./configure --prefix=/usr/local/gcc-4.6.2 > Thread model: posix > gcc version 4.6.2 (GCC) > >> ld -v > GNU ld version 2.17.50.0.6-14.el5 20061020