sizeof an object that have same base class as member objects.

Y

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....0/2148a6c1ac6119e1?lnk=st&q=#2148a6c1ac6119e1

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) I dug
through the bugbase but couldn't come up with anything. Maybe EBO
isn't the problem at all.

Thanks!
 
I

Ian Collins

Yen said:
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.
I would have expected sizeof(group) to be 12 (even without the gcc
specific __attribute__), looks like a bug.

It is 12 with Sun CC.
Is this a known bug with gcc 3.4.5? (Note: I'm using MinGW) I dug
through the bugbase but couldn't come up with anything. Maybe EBO
isn't the problem at all.
4.0.0 also reports 13 and 16 without the __attribute__ directive.
 
Y

Yen Kwoon

Then Sun CC seems to be wrong.
That means Microsoft VS8 compiler and RVCT ARM compiler are wrong as
well :-(
I agree with the opinions expressed in the cited gnu.gcc.help thread: the
base class subobject of the group class and the base class subobject of
d1 are of the same type and cannot be assigned the same address (I
believe the general intent is that no two objects of the same type may
have the same address):

"In 10.0.5:
A base class subobject may be of zero size (clause 9); however,
two subobjects that have the same class type and that belong to
the same most derived object must not be allocated at the same
address (5.10).
"

Thus I think gcc is correct to assign size 13 to the group class. Note
that this will hurt performance because of misaligned access if you are
using arrays of group objects (and otherwise you would not have to worry
about its size, right?). But by specifying __attribute__ you have told
the compiler you know better.
You are probably correct. The original motivation of transplanting
this question to this group is to verify that the specification in
question is relevant. Did gcc interpret that paragraph correctly
whereas the other 3 compilers failed to?
Hopefully readers on this group can try out the same code on more
compilers and report the results.
 
J

James Kanze

* Yen Kwoon:
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.)
 
J

James Kanze

* James Kanze:

[...]
Oh, no problemo. :) For the in-practice the compiler can let
the address of an empty base class sub-object be (or seem to
be) anything, as long as it's unique for that complete object,
and as long as assignments are translated to no-ops.

In theory, yes, but it's going to be tricky if == and != are
going to work correctly, along with the implicit casts down and
the explicit casts up.
But for a moment, after reading Paavo's replies and before
reading yours (I instinctively think when reading your
articles, although not always successfully), I thought the
same as you write here, and would probably have written
something along those lines, to correct myself, if you hadn't
caused me to think...
The problem here is that the formal seems to refer to the in-practice:
"allocated at the same address" seems to say something about
reality, not about the abstract machine's &-operator.

Now that you mention it, it does sound like the wording could
stand some improvement.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top