Structure alignment changes when a constructor or destructor is added

Jonathan Wakely jwakely.gcc@gmail.com
Tue Dec 6 22:31:00 GMT 2011


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



More information about the Gcc-help mailing list