Re: sizeof() class with empty base class
actually, in theory, I think that sizeof(Matrix4x4) should be strictly greater then 16*sizeof(float) as far as standard C++ is concerned, and so that GCC is correct and that VC++ is wrong.
indeed, according to
Quote:
Originally Posted by C++2003 - 10.5
A base class subobject might have a layout (3.7) different from the layout of a most derived object of the same type. A base class subobject might have a polymorphic behavior (12.7) different from the polymorphic behavior of a most derived object of the same type. 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).
the rationale being that every distinct object of the same type should have a distinct address. So, the code
Code:
struct Base
{
// helper functions here
};
struct Vector4 : public Base
{
float x, y, z, w;
};
struct Matrix4x4 : public Base
{
Vector4 rows[4];
};
int main()
{
Matrix4x4 m;
Base* pb1 = &m;
Base* pb2 = m.rows;
_ASSERT( pb1 != pb2 );
}
should never fail on a conforming compiler ( and fails on VC++2008 ); that said, a quick google search on the subject shows that compilers generally behave weirdly on this regard and, to be honest, that the standard is not very clear on this point ( for example, what does it mean "allocating an object of zero size" ? I mean, is the compiler allowed, say, to set the address of the second Base subobject to <any> address included in the memory region spanned by subobjects of different type ? )
Re: sizeof() class with empty base class
I think superbonzo wins a prize. It's spelled out in the definition of a standard-layout class in section 9 paragraph 6, which refers to that 5.10 rule.
Quote:
6. A standard-layout class is a class that:
— has no non-static data members of type non-standard-layout class (or array of such types) or reference,
— has no virtual functions (10.3) and no virtual base classes (10.1),
— has the same access control (Clause 11) for all non-static data members,
— has no non-standard-layout base classes,
— either has no non-static data members in the most-derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and
— has no base classes of the same type as the first non-static data member. This ensures that two subobjects that have the same class type and that belong to the same most-derived object are not allocated at the same address (5.10).
GCC is trying to do exactly that-- ensure that two Base pointers point to different memory even if they come from the beginning of the same object. Not exactly sure why that's a problem though. Still thinking about that.
This following proves that GCC is following that rule:
Code:
// sizeof( Matrix4x4 ) == 64 (exact size)
struct Matrix4x4 : Base
{
Vector4NoBase row0;
Vector4 row1, row2, row3;
};
Unfortunately I don't know of a way to tell GCC that to me it's ok that ( &m == &m.row ). So I have to resort to not using empty base classes. Not that big a deal.
Re: sizeof() class with empty base class
Have you tried #pragma pack(1)? It'll change the generated code to make the class take as little memory as possible instead of optimizing it for performance.
I'm also curious to how VC++ does vtables, sizeof(object with 64 bytes of members) should not equal 64. What does this output on VC++?
Code:
#include <iostream>
class foo {
//empty
};
int main(int argc, char**argv){
cout << sizeof(foo) << endl;
}
Re: sizeof() class with empty base class
Quote:
Originally Posted by
ninja9578
Have you tried #pragma pack(1)? It'll change the generated code to make the class take as little memory as possible instead of optimizing it for performance.
Thanks for the suggestion ninja. I tried pragma pack out of curiosity even though I don't want to disable native alignment, but GCC still adhered to that 9-6 rule. sizeof(Matrix4x4) became 65 instead of 68. It has to add at least one byte to make &m different from &m.row0.
GCC is correct. It's doing what was told by the standard.
Re: sizeof() class with empty base class
Quote:
Originally Posted by
chopin952
Thanks for the suggestion ninja. I tried pragma pack out of curiosity even though I don't want to disable native alignment,
pragma pack() is only useful for POD structs or classes.
You started introducing derived classes, virtual functions, etc. effectively making the types you're using non-POD. Once you do that, then you are leaving the "well defined" world of C, and entering the world of C++ where what you may think works doesn't work.
Regards,
Paul McKenzie
Re: sizeof() class with empty base class
Just to give a related example when it comes to POD and non-POD types, a lot of 'C' programmers who learn C++ start to write code like this. What winds up happening is that code like this stumps them, because it looks like it should work, but instead fails miserably:
Code:
#include <string>
#include <stdlib.h>
#include <iostream>
int main()
{
std::string* p = (std::string*)malloc(sizeof(std::string));
std::cout << *p; // should print a blank string
free(p);
}
What could go wrong? You're creating a std::string from the heap, calling the operator << for it, and then freeing it. But the problem is at the very start -- a std::string object was not created at all. A serious of bytes were allocated, but no object creation occurred. So the p is totally bogus if attempting to call member functions through it. You can add to this example the memcpy() bug that a lot of programmers encounter when given a pointer to a non-POD type, and they just wipe out the object with zeros or some other value.
Once non-POD types enter the picture, you have to drop the 'C' way of thinking how things should work. You will get burned by it at some point.
Regards,
Paul McKenzie
Re: sizeof() class with empty base class
Paul I appreciate your answers, but why the pedantic need to point out the stupidities of programmers in years past? That std::string example is at the very least mildly insulting.
I know I'm new on this forum. So some slight background info is probably necessary. I have not been a C programmer in practice. I started with Pascal then moved directly to C++ and have been programming professionally since 1997. And please don't go into, "oh if you had programmed C, you would understand C++ better."
I intended this post to be more technical than "hey guys my program no compile, why no compile? What does stdio stand for? Visual Studio?"
Anyway. #pragma pack still works on non-POD. Just because a construct is C++, OO, derived, with virtuals, etc... doesn't mean you shouldn't care about data layout. If I want to allocate 256 of my Matrix4x4, I care that GCC is making me waste 1KB. My original intent with the example was to make a POD structure with the convenience of an empty base, which is invoking an interesting rule in C++, that even our beloved VisualC++ is not respecting. Maybe the MS programmers thought otherwise when it came to that rule.
I'm going to accomplish what I want without the derivation. And even use C-style containment when I need actual base data, to avoid the pitfalls of a vague standard and various compilers. I may even switch to C to feel even more pure.
Thanks for your 23K+ posts.
Are you on the east coast? Let's get together for an in-depth conversation about the usefulness of template meta-programming over some beer.
Regards.
-Amilcar
Re: sizeof() class with empty base class
Quote:
Originally Posted by
chopin952
Paul I appreciate your answers, but why the pedantic need to point out the stupidities of programmers in years past?
Have you read the threads here? You will see that there are many threads where the programmer makes mistakes such as above.
Quote:
That std::string example is at the very least mildly insulting.
Check the qsort() vs. std::sort thread that ran here about 10 or so years ago if you want a more advanced example. That was case of 'C' thinking being applied to a C++ program, and the pitfalls assuming that C++ works the same.
Also, my post is not made to insult anyone -- you are anonymous here and no one knows your level of expertise, plus this is not a private thread -- others are reading it and can learn from the various insights and posts here, including the one I made about assuming that malloc() is the same as new (and again, you will see scores of threads about this). But the main point I was trying to make is that C++ is not 'C' when it comes to trying to "think out" what should happen using 'C' as a guideline or base.
Quote:
I know I'm new on this forum. So some slight background info is probably necessary. I have not been a C programmer in practice. I started with Pascal then moved directly to C++ and have been programming professionally since 1997.
Well, I've gone past 25 years of programming professionally, and 20 years of C++.
Quote:
And please don't go into, "oh if you had programmed C, you would understand C++ better."
No way. I'm one of the ones that complains the most about persons learning 'C" programming before C++ to "get a head start", or the poor ways that students are learning C++ as if it's C with some new syntax. I've usually just directed them to this thread:
http://www.parashift.com/c++-faq-lit....html#faq-28.2
Quote:
Anyway. #pragma pack still works on non-POD. Just because a construct is C++, OO, derived, with virtuals, etc... doesn't mean you shouldn't care about data layout.
The issue really is that you have little control over the non-POD parts of the layout. What works today may not work on a later version of the compiler.
Anyway, if you have a solution, and it's sound, then I have no complaints.
Edit:
And BTW, the qsort()/std::sort thread is one of the longest here. The 'C' guy got banned here because he was flabbergasted that his qsort() wasn't beating std::sort, and to top it off, his solution didn't work for a certain compiler if the types were non-POD. He was so sure of himself, but he couldn't show some humility that his "solution" was no solution. At the end of that thread (or another thread), he started to go off the deep end and started personal insults, giving rise to his being banned here.
Regards,
Paul McKenzie
Re: sizeof() class with empty base class
Understood. I searched a bit looking for a C++ forum on which to post, and most I found had the inane beginner mind-bogglers. I chose this one because it was primarily VC++ with a non-VC++ section, and hoped there would be some veterans around with who to brainstorm.
Cheers.
Re: C/C++. Who starts learning with C these days, let alone as a bridge to C++? When I talk to new graduates of my local college, all they talk about is Java and Flash. Some of the more intense courses when C was taught here like Data Structures, Linear Algebra, and Automata Theory are either missing or seemingly dumb-down and suffixed "...for Engineers" bah.
edit: Do you know of other good active C/C++ forums, preferably with cross-platform/cross-compiler concerns?
Re: sizeof() class with empty base class
Quote:
Originally Posted by
Paul McKenzie
Edit:
And BTW, the qsort()/std::sort thread is one of the longest here. The 'C' guy got banned here because he was flabbergasted that his qsort() wasn't beating std::sort, and to top it off, his solution didn't work for a certain compiler if the types were non-POD. He was so sure of himself, but he couldn't show some humility that his "solution" was no solution. At the end of that thread (or another thread), he started to go off the deep end and started personal insults, giving rise to his being banned here.
Nice. I'll have to catch up on that thread. I always like reading the roller coaster of a sane thread turn personal. Like a geeky soap opera. hah.
Don't worry. Over the years I've learned to bow to humility as soon as it is possible. No need in being hard headed only to have to disappear in shame when conclusively proven wrong. You notice how I started with "VC++ is correct and GCC looks wrong." It was soon reversed with proper investigation.
Best,
-Amilcar
Re: sizeof() class with empty base class
Quote:
Originally Posted by
Paul McKenzie
, he started to go off the deep end and started personal insults, giving rise to his being banned here.
AnthonyMai ?
I've just been browsing some of the old threads. Ay Caramba!
Re: sizeof() class with empty base class
I liked this response to one of his replies.
"The poster who made the complaint is known for having issues with functions that do what they are defined to do. If any function does not do "what he thinks it should do", that is grounds for complaint [in his eyes]."
Re: sizeof() class with empty base class
Quote:
Originally Posted by
chopin952
Who starts learning with C these days, let alone as a bridge to C++? When I talk to new graduates of my local college, all they talk about is Java and Flash. Some of the more intense courses when C was taught here like Data Structures, Linear Algebra, and Automata Theory are either missing or seemingly dumb-down and suffixed "...for Engineers" bah.
It can be difficult to find a good C++ class these days. In retrospect, my high school AP CS course was better in that respect than college was. While my high school class didn't actually teach STL, it at least required us to use their "apvector" class rather than arrays, which was a good start although I didn't appreciate it at the time.
Once I got to Carnegie Mellon, there was a notable anti-C++ bias. There was a C class (which, bless them, taught us how to use man pages), and there were Java classes, and even SML classes. But I don't recall any C++ classes, and certainly none that taught it the "right" way.