A member variable of a class that utilizes EBO and has a type that also utilizes EBO appears to be laid out at the wrong offset. In the example below, the only difference between the classes Good and Bad is that the member of Bad inherits from a class with no members. The sizeof printouts show that EBO is in play, but the Bad class gets an extra four byte padding before the member. There's no reason Bad should be any larger than Good. Kind Regards /David #include <cstdio> struct Empty { }; struct Member { int extent; }; struct MemberWithEBO : public Empty { int extent; }; struct Good : public Empty { Member m; }; // OK struct Bad : public Empty { MemberWithEBO m; }; // Broken, see below #define PRINT(x) printf ("%-25s %d\n", # x ":", (x)) template <typename C, typename T> long int offsetOf (T C::*m) { C proto; return (long int)(void*)&(proto.*m) - (long int)(void *)&proto; } int main (int argc, char ** argv) { PRINT (sizeof (Member)); PRINT (sizeof (Good)); PRINT (offsetOf (&Good::m)); PRINT (sizeof (MemberWithEBO)); PRINT (sizeof (Bad)); PRINT (offsetOf (&Bad::m)); } // Printout: // // sizeof (Member): 4 // sizeof (Good): 4 // offsetOf (&Good::m): 0 // sizeof (MemberWithEBO): 4 // sizeof (Bad): 8 <-- Should be 4 // offsetOf (&Bad::m): 4 <-- Should be 0 > g++ -v -save-temps ebo_bug.cc Using built-in specs. Target: x86_64-unknown-linux-gnu Configured with: ../configure --prefix=/usr/local/gcc431 --with-pkgversion=gcc431 --enable-languages=c,c++ Thread model: posix gcc version 4.3.1 (gcc431) COLLECT_GCC_OPTIONS='-v' '-save-temps' '-shared-libgcc' '-mtune=generic' /usr/local/gcc431/libexec/gcc/x86_64-unknown-linux-gnu/4.3.1/cc1plus -E -quiet -v -D_GNU_SOURCE ebo_bug.cc -mtune=generic -fpch-preprocess -o ebo_bug.ii ignoring nonexistent directory "/usr/local/gcc431/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/../../../../x86_64-unknown-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/local/gcc431/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/../../../../include/c++/4.3.1 /usr/local/gcc431/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/../../../../include/c++/4.3.1/x86_64-unknown-linux-gnu /usr/local/gcc431/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/../../../../include/c++/4.3.1/backward /usr/local/include /usr/local/gcc431/include /usr/local/gcc431/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/include /usr/local/gcc431/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/include-fixed /usr/include End of search list. COLLECT_GCC_OPTIONS='-v' '-save-temps' '-shared-libgcc' '-mtune=generic' /usr/local/gcc431/libexec/gcc/x86_64-unknown-linux-gnu/4.3.1/cc1plus -fpreprocessed ebo_bug.ii -quiet -dumpbase ebo_bug.cc -mtune=generic -auxbase ebo_bug -version -o ebo_bug.s GNU C++ (gcc431) version 4.3.1 (x86_64-unknown-linux-gnu) compiled by GNU C version 4.3.1, GMP version 4.1.4, MPFR version 2.2.1. GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: 4926fc16e15403c044148a60354159ba COLLECT_GCC_OPTIONS='-v' '-save-temps' '-shared-libgcc' '-mtune=generic' as -V -Qy -o ebo_bug.o ebo_bug.s GNU assembler version 2.17.50.0.6-6.el5 (x86_64-redhat-linux) using BFD version 2.17.50.0.6-6.el5 20061020 COMPILER_PATH=/usr/local/gcc431/libexec/gcc/x86_64-unknown-linux-gnu/4.3.1/:/usr/local/gcc431/libexec/gcc/x86_64-unknown-linux-gnu/4.3.1/:/usr/local/gcc431/libexec/gcc/x86_64-unknown-linux-gnu/:/usr/local/gcc431/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/:/usr/local/gcc431/lib/gcc/x86_64-unknown-linux-gnu/ LIBRARY_PATH=/usr/local/gcc431/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/:/usr/local/gcc431/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/local/gcc431/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-v' '-save-temps' '-shared-libgcc' '-mtune=generic' /usr/local/gcc431/libexec/gcc/x86_64-unknown-linux-gnu/4.3.1/collect2 --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/../lib64/crt1.o /usr/lib/../lib64/crti.o /usr/local/gcc431/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/crtbegin.o -L/usr/local/gcc431/lib/gcc/x86_64-unknown-linux-gnu/4.3.1 -L/usr/local/gcc431/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/local/gcc431/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/../../.. ebo_bug.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/local/gcc431/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/crtend.o /usr/lib/../lib64/crtn.o
Created attachment 16474 [details] Preprocessed program
Do you have evidence that this is a bug given the detailed specifications of the ABI document: http://www.codesourcery.com/public/cxx-abi/ ??? I have trouble believing it, and just checked that other compilers conforming to the multi-vendor standard ABI behave exactly the same as GCC...
Ah, no, I wasn't aware of that document. I just thought that gcc was treating the Good and Bad cases inconsitently. Now, in layman's terms, is the reason for the padding that no two distinct instances of Empty may share the same address? If that is the case, it would explain the padding and this is not a bug. Sorry, should have investigated more before hitting the commit button. /David
(In reply to comment #3) > Now, in layman's terms, is the reason for the padding that no two distinct > instances of Empty may share the same address? If that is the case, it would > explain the padding and this is not a bug. Yes, that is a very basic requirement that EBO cannot circumvent. About layman' explanations of the basic logic, I suggest paragraph 16.2 of "C++ Templates: The Complete Guide".
Subject: Re: Member variable of empty base optimized (EBO) class appears on wrong offset Iirc there are some pod vs non pod issues here dealing wit padding and the c++ standard and not even the abi. Sent from my iPhone On Oct 7, 2008, at 2:31 AM, "david dot rosenborg at pantor dot com" <gcc-bugzilla@gcc.gnu.org > wrote: > > > ------- Comment #3 from david dot rosenborg at pantor dot com > 2008-10-07 09:31 ------- > Ah, no, I wasn't aware of that document. I just thought that gcc was > treating > the Good and Bad cases inconsitently. > > Now, in layman's terms, is the reason for the padding that no two > distinct > instances of Empty may share the same address? If that is the case, > it would > explain the padding and this is not a bug. > > Sorry, should have investigated more before hitting the commit button. > > /David > > > -- > > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37762 >