473,657 Members | 2,266 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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

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
7 1961
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
Ian Collins <ia******@hotma il.comwrote in news:69n4jrF337 gaaU7
@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
>
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
Yen Kwoon <Ye******@gmail .comwrote in
news:80******** *************** ***********@b5g 2000pri.googleg roups.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
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.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(pack ed)") 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 objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #6
Paavo Helde <no****@ebi.eew rote in
news:Xn******** *************** **@216.196.97.1 31:
Yen Kwoon <Ye******@gmail .comwrote in
news:80******** *************** ***********@b5g 2000pri.googleg roups.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
On 23 mai, 11:06, "Alf P. Steinbach" <al...@start.no wrote:
* 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 objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
3547
by: Sunil Menon | last post by:
Dear All, A class having no member variables and only a method sizeof(object) will return 1byte in ANSI and two bytes in Unicode. I have the answer for this of how in works in ANSI. But I don't know it returns two bytes in UniCode. Please help... For ANSI: In ISO/ANSI C++ Standard, 5.3.3 § 1, it stays: "The sizeof operator yields the number of bytes in the object representation of its
44
2441
by: Steven T. Hatton | last post by:
This may seem like such a simple question, I should be embarrassed to ask it. The FAQ says an object is "A region of storage with associated semantics." OK, what exactly is meant by "associated semantics"? What, if any, associated semantics are shared by all objects? That part seems to go beyond the FAQ. Does anybody know of a resource that discusses (focuses on) this topic? -- p->m == (*p).m == p.m
4
3102
by: Gopal-M | last post by:
I have the problem with sizeof operator I also want to implement a function that can return size of an object. My problem is as follows.. I have a Base class, say Base and there are many class derived from it. At a particular point in my application I need the size of the object pointed to by the base pointer. Eg
2
2456
by: Xiangliang Meng | last post by:
Hi, all. What will we get from sizeof(a class without data members and virtual functions)? For example: class abnormity { public: string name() { return "abnormity"; }
5
2113
by: Jeff Greenberg | last post by:
Not an experienced c++ programmer here and I've gotten myself a bit stuck. I'm trying to implement a class lib and I've run into a sticky problem that I can't solve. I'd appreciate any help that I can get! Consider 3 classes in the following heirarchy: base / \ deriv1 deriv2 \
2
2206
by: lpw | last post by:
I have dilligently reviewed FAQ-lite Section 3.2, "How do I pass a pointer-to-member-function to a signal handler, X event callback, system call that starts a thread/task, etc." The only suggestion on how to deliver a signal to an object is to do it via a global variable and a wrapper function, a technique that is generally a Bad Idea (due to the usage of a global variable). I understand that this ng is dedicated to the discussion of...
0
1579
by: Cat | last post by:
I have class Base, and class Derived. I am serializing Derived objects from XML, and these Derived objects are allowed to 'inherit' the values from other named Base objects already defined in the XML. <Base name="cat"/> <Derived name="tabby" inherits="cat"/> Some Derived objects are not fully described in the XML, and their members
32
2161
by: moleskyca1 | last post by:
This may be stupid question, but why is sizeof(Base) == 1 in: int main(int argc, char* argv) { class Base { }; cout << sizeof(Base) << endl; return 0; }
6
4130
by: Rick | last post by:
Hi, Can anyone explain to me why the below fails to compile - seeing otherA->f(); as a call to a inaccessible function, while otherB->f(); is ok? It seems you can happily access protected functions of another (same type) - but not via a base class pointer.... I've checked the FAQs, Meyers etc but nothing obvious I can find explains it.
0
8319
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8837
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
8512
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
7347
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6175
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5638
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4329
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2739
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
1969
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.