By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,542 Members | 1,740 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,542 IT Pros & Developers. It's quick & easy.

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

P: n/a
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.g...48a6c1ac6119e1

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!
Jun 27 '08 #1
Share this Question
Share on Google+
7 Replies


P: n/a
Yen Kwoon wrote:
>
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.

--
Ian Collins.
Jun 27 '08 #2

P: n/a
Ian Collins <ia******@hotmail.comwrote in news:69n4jrF337gaaU7
@mid.individual.net:
Yen Kwoon wrote:
>>
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.
Then Sun CC seems to be wrong.

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.

Regards
Paavo
>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.
Jun 27 '08 #3

P: n/a
>
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.
Jun 27 '08 #4

P: n/a
Yen Kwoon <Ye******@gmail.comwrote in
news:80**********************************@b5g2000p ri.googlegroups.com:
>>
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.
I am not so great in legalese - I'm trying to understand the overall
objectives and design criterias, and in this case I believe the intent is
that however you get hold of two addresses to the different objects of
the same type, these should not compare equal.

FWIW, I tried the following in Comeau online and it agrees with gcc.
Comeau is very seldom wrong...

#pragma pack(1)

class base {
public:
base(){};
~base(){};

};

class data : public base {
public:
data(){};
~data(){};
private:
int member;

};

class group : public base {
public:
group(){};
~group(){};
private:
data d1;
data d2;
data d3;

};

int array[sizeof(group)-12]; // works
// int array[sizeof(group)-13]; // fails, array size cannot be zero


Jun 27 '08 #5

P: n/a
On May 23, 7:56 am, "Alf P. Steinbach" <al...@start.nowrote:
* 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.g...ad/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:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #6

P: n/a
Paavo Helde <no****@ebi.eewrote in
news:Xn*************************@216.196.97.131:
Yen Kwoon <Ye******@gmail.comwrote in
news:80**********************************@b5g2000p ri.googlegroups.com:
>>>
Then Sun CC seems to be wrong.
That means Microsoft VS8 compiler and RVCT ARM compiler are wrong as
well :-(
Would not be the first time (at least for VS8).

And this gives sizeof(group)==12 in Comeau:

#pragma pack(1)

template<class T>
class base {
public:
base(){};
~base(){};

};

class data : public base<data{
public:
data(){};
~data(){};
private:
int member;

};

class group : public base<group{
public:
group(){};
~group(){};
private:
data d1;
data d2;
data d3;

};

int array[sizeof(group)-11];
// int array[sizeof(group)-12]; // fails
Jun 27 '08 #7

P: n/a
On 23 mai, 11:06, "Alf P. Steinbach" <al...@start.nowrote:
* James Kanze:
[...]
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.
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.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #8

This discussion thread is closed

Replies have been disabled for this discussion.