Re: sizeof an object that have same base class as member objects.
On May 23, 7:56 am, "Alf P. Steinbach" <al...@start.no> wrote:
* Yen Kwoon:
Note: This problem is related to gcc but after some back and forth in
group gnu.gcc.help it seems to have morph into more of a c++
specificiation question, hence the transplanting to this group.
The original post at gnu.gcc.help can be found at this link
http://groups.google.com/group/gnu.gcc.help/browse_thread/thread/ece5...
Here's the question:
class base {
public:
base(){};
~base(){};
};
class data : public base {
public:
data(){};
~data(){};
private:
int member;
}__attribute__((__packed__));
class group : public base {
public:
group(){};
~group(){};
private:
data d1;
data d2;
data d3;
} __attribute__((__packed__));
int main(int argc, char **argv) {
std::cout << "base = " << sizeof(base) << std::endl;
std::cout << "data = " << sizeof(data) << std::endl;
std::cout << "group = " << sizeof(group) << std::endl;
return (0);
}
The output of the program is:
base = 1
data = 4
group = 13
The result of sizeof(group) is puzzling as it should be 12
if EBO (empty base optimization) worked for both class data
and group. Apparently EBO kicked in for _ONLY_ one of them.
If EBO didn't work at all, sizeof(group) should be 16.
Removing the extension of class base from either class group
or data will cause sizeof(group) to return 12. It seems that
gcc is unable to fully apply EBO when a class and its member
inherits the same empty base class.
The same code had been tested on microsoft msvc compiler and
realview arm compiler, both correctly optimizes the code and
give the correct value as 12.
Is this a known bug with gcc 3.4.5? (Note: I'm using MinGW)
Only if the compiler's specification (in this case presumably
of non-standard extension "attribute(packed)") says it should
apply EBO.
The standard does not require any optimization.
For example, a compiler where sizeof(bool) == 4000000 is conforming.
The question is misstated, first because the example code isn't
standard C++ (so we can't really say what the standard says
about it), and second because the problem has nothing to do with
size anyway (and as you point out, the standard doesn't really
make any guarantees with regards to size). Add the following
function to base:
base* base::addr() { return this ; }
make all of the members public, then try:
int
main()
{
group g ;
assert( g.addr() != g.d1.addr() ) ;
}
That assertion is guaranteed to pass: the standard does not
allow g.addr() (which returns the address of base in group) to
be equalt to g.d1.addr() (which returns the address of base in
data). It doesn't fail with g++, so g++ is fine. It does fail
with both Sun CC and VC++, so those compilers have an error.
(I don't believe that it's possible to correctly implement this
on a 32 bit machine and still have sizeof(group) == 12. But the
standard doesn't say one way or the other; the fact that VC++ or
Sun CC say sizeof(group) == 12 is NOT an error per se on their
part. The fact that the above assertion fails is, however.)
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34