After seeing this question a few minutes ago, I wondered why the language designers allow it as it allows indirect modification of private data. As an example
class TestClass {
private:
int cc;
public:
TestClass(int i) : cc(i) {};
};
TestClass cc(5);
int* pp = (int*)&cc;
*pp = 70; // private member has been modified
I tested the above code and indeed the private data has been modified. Is there any explanation of why this is allowed to happen or this just an oversight in the language? It seems to directly undermine the use of private data members.
Because, as Bjarne puts it, C++ is designed to protect against Murphy, not Machiavelli.
In other words, it's supposed to protect you from accidents -- but if you go to any work at all to subvert it (such as using a cast) it's not even going to attempt to stop you.
When I think of it, I have a somewhat different analogy in mind: it's like the lock on a bathroom door. It gives you a warning that you probably don't want to walk in there right now, but it's trivial to unlock the door from the outside if you decide to.
Edit: as to the question #Xeo discusses, about why the standard says "have the same access control" instead of "have all public access control", the answer is long and a little tortuous.
Let's step back to the beginning and consider a struct like:
struct X {
int a;
int b;
};
C always had a few rules for a struct like this. One is that in an instance of the struct, the address of the struct itself has to equal the address of a, so you can cast a pointer to the struct to a pointer to int, and access a with well defined results. Another is that the members have to be arranged in the same order in memory as they are defined in the struct (though the compiler is free to insert padding between them).
For C++, there was an intent to maintain that, especially for existing C structs. At the same time, there was an apparent intent that if the compiler wanted to enforce private (and protected) at run-time, it should be easy to do that (reasonably efficiently).
Therefore, given something like:
struct Y {
int a;
int b;
private:
int c;
int d;
public:
int e;
// code to use `c` and `d` goes here.
};
The compiler should be required to maintain the same rules as C with respect to Y.a and Y.b. At the same time, if it's going to enforce access at run time, it may want to move all the public variables together in memory, so the layout would be more like:
struct Z {
int a;
int b;
int e;
private:
int c;
int d;
// code to use `c` and `d` goes here.
};
Then, when it's enforcing things at run-time, it can basically do something like if (offset > 3 * sizeof(int)) access_violation();
To my knowledge nobody's ever done this, and I'm not sure the rest of the standard really allows it, but there does seem to have been at least the half-formed germ of an idea along that line.
To enforce both of those, the C++98 said Y::a and Y::b had to be in that order in memory, and Y::a had to be at the beginning of the struct (i.e., C-like rules). But, because of the intervening access specifiers, Y::c and Y::e no longer had to be in order relative to each other. In other words, all the consecutive variables defined without an access specifier between them were grouped together, the compiler was free to rearrange those groups (but still had to keep the first one at the beginning).
That was fine until some jerk (i.e., me) pointed out that the way the rules were written had another little problem. If I wrote code like:
struct A {
int a;
public:
int b;
public:
int c;
public:
int d;
};
...you ended up with a little bit of self contradition. On one hand, this was still officially a POD struct, so the C-like rules were supposed to apply -- but since you had (admittedly meaningless) access specifiers between the members, it also gave the compiler permission to rearrange the members, thus breaking the C-like rules they intended.
To cure that, they re-worded the standard a little so it would talk about the members all having the same access, rather than about whether or not there was an access specifier between them. Yes, they could have just decreed that the rules would only apply to public members, but it would appear that nobody saw anything to be gained from that. Given that this was modifying an existing standard with lots of code that had been in use for quite a while, the opted for the smallest change they could make that would still cure the problem.
Because of backwards-compatability with C, where you can do the same thing.
For all people wondering, here's why this is not UB and is actually allowed by the standard:
First, TestClass is a standard-layout class (§9 [class] p7):
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, // OK: non-static data member is of type 'int'
has no virtual functions (10.3) and no virtual base classes (10.1), // OK
has the same access control (Clause 11) for all non-static data members, // OK, all non-static data members (1) are 'private'
has no non-standard-layout base classes, // OK, no 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 // OK, no base classes again
has no base classes of the same type as the first non-static data member. // OK, no base classes again
And with that, you can are allowed to reinterpret_cast the class to the type of its first member (§9.2 [class.mem] p20):
A pointer to a standard-layout struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa.
In your case, the C-style (int*) cast resolves to a reinterpret_cast (§5.4 [expr.cast] p4).
A good reason is to allow compatibility with C but extra access safety on the C++ layer.
Consider:
struct S {
#ifdef __cplusplus
private:
#endif // __cplusplus
int i, j;
#ifdef __cplusplus
public:
int get_i() const { return i; }
int get_j() const { return j; }
#endif // __cplusplus
};
By requiring that the C-visible S and the C++-visible S be layout-compatible, S can be used across the language boundary with the C++ side having greater access safety. The reinterpret_cast access safety subversion is an unfortunate but necessary corollary.
As an aside, the restriction on having all members with the same access control is because the implementation is permitted to rearrange members relative to members with different access control. Presumably some implementations put members with the same access control together, for the sake of tidiness; it could also be used to reduce padding, although I don't know of any compiler that does that.
The whole purpose of reinterpret_cast (and a C style cast is even more powerful than a reinterpret_cast) is to provide an escape path around safety measures.
The compiler would have given you an error if you had tried int *pp = &cc.cc, the compiler would have told you that you cannot access a private member.
In your code you are reinterpreting the address of cc as a pointer to an int. You wrote it the C style way, the C++ style way would have been int* pp = reinterpret_cast<int*>(&cc);. The reinterpret_cast always is a warning that you are doing a cast between two pointers that are not related. In such a case you must make sure that you are doing right. You must know the underlying memory (layout). The compiler does not prevent you from doing so, because this if often needed.
When doing the cast you throw away all knowledge about the class. From now on the compiler only sees an int pointer. Of course you can access the memory the pointer points to. In your case, on your platform the compiler happened to put cc in the first n bytes of a TestClass object, so a TestClass pointer also points to the cc member.
This is because you are manipulating the memory where your class is located in memory. In your case it just happen to store the private member at this memory location so you change it. It is not a very good idea to do because you do now know how the object will be stored in memory.
Related
I want to detect during compile time (static assertion) whether a class meets both the following conditions:
Has an implicit default constructor (i.e., no user-defined default constructor).
Has at least one data member which is a pod (i.e., a member whose default initialization is to assume whatever random bytes was in its memory address).
[I hope I used the term pod correctly here]
The idea is to avoid working with objects with uninitialized members. I know there are different methods to do this during coding, but I also want a mechanism to detect this during compilation.
I tried using different std/boost functions, such as is_trivially_constructible, is_pod, but none of these provide the exact terms I need.
For example, let's say I have the following classes:
struct A
{
int a;
}
struct B
{
int* b;
}
struct C
{
bool c;
std::string c_str_;
}
struct D
{
D();
float d;
}
struct E
{
std::string e;
}
Assuming the function I need is called "has_primitive_and_implicit_ctor", I would like the output for each call to be as in the comments:
has_primitive_and_implicit_ctor<A>(); //true - A has at least one pod type member (int)
has_primitive_and_implicit_ctor<B>(); //true - A has at least one pod type member (pointer)
has_primitive_and_implicit_ctor<C>(); //true - A has at least one pod type member (bool), even though there is one non-pod member
has_primitive_and_implicit_ctor<D>(); //false - has a pod member(float), but a user defined ctor
has_primitive_and_implicit_ctor<E>(); //false - doesn't have a default ctor but has no pod members
Firstly, it seems to me like a broken design to expect from the user of a class to care about its member initialisation. You should make sure in the class itself that all its members are initialised, not somewhere else where it is used.
What you are looking for does not exist, and if it would, it would not even help you. The existence of an explicit constructor does not guarantee that a data member is initialised. On the other hand, with C++11 it is even possible to initialise data members without explicitly writing a constructor (using the brace syntax in the class declaration). Also you just seem to care about uninitialised POD members, but what about uninitialised non-POD members?
That said, compiler can generate warnings about uninitialised values, but often you have to enable this warning (e.g. -Wuninitialized option for gcc). Most compilers allow to force treating warnings as an error. In combination this can give you the desired effect even without specifically writing code to test for it, and it would also work for any uninitialised values, not only those in classes. Maybe this is the solution you are looking for.
Question: Is there an automatic way to do structure packing?
Background:
Structure packing is very useful to reduce the memory cost of certain fundamental data. Basically it is the trick to achieve minimum memory cost by reordering the data inside. My question is that is there an auto way to do that? For example, I have a struct Foo here.(suppose 32bit)
struct Foo {
char flag;
char* p;
short number;
};
After a auto check(either it is a script or not, native or not), I should get a memory-optimization version of Foo, which is:
struct Foo {
char* p;
short number;
char flag;
};
This is just a toy example. Consider more difficult situations below, it would be quite a work for manual reordering.
struct has dependent struct:
struct Foo {
char* p;
short number;
MoreFoo more_foo // How to deal with this?
char flag;
};
struct is in legacy code and you are not familiar with codebase.
you want the code to be cross-platform. Sadly enough, this trick is compiler-dependent.
I am not considering using "packed" attribute since it will lead to some performance issue.
Can __attribute__((packed)) affect the performance of a program?
In C++03 you can give the compiler permission to reorder members by placing every one inside a separate access section, e.g.:
struct Foo
{
public:
char* p;
public:
short number;
public:
MoreFoo more_foo;
public:
char flag;
};
Whether a particular compiler uses this additional flexibility or not I do not know.
This doesn't change the declaration order, it simply unlinks memory order from declaration order, so PaulMcKenzie's concern about initialization order does not apply. (And I think he overstated the concern; it is very rare for member initializers to refer to other subobjects in the first place)
The way this works is because it causes the following rule, from 9.2) to no longer have effect:
Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of allocation of nonstatic data members separated by an access-specifier is unspecified (11.1). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).
Also, it's questionable whether this still works in C++11, since the wording changed from "without an intervening access-specifier" to "with the same access control":
Nonstatic data members of a (non-union) class with the same access control (Clause 11) are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified (Clause 11). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).
In C programming, automatic optimization of a struct is not possible because this would go against the very way it was designed. C allows low-level access to the hardware, in fact, it is only a step higher from assembly language. It is designed to create dependent code that controls hardware.
Given this, unfortunately, you can only re-order a struct manually. You would probably need to find the size of all the struct's attributes, as so:
printf ("Size of char is %d\n", sizeof (char));
printf ("Size of char* is %d\n", sizeof (char*));
printf ("Size of short is %d\n", sizeof (short));
printf ("Size of MoreFoo is %d\n", sizeof (MoreFoo more_foo));
And then order the struct based on these values.
Say I have some data allocated somewhere in my program, like:
some_type a;
and I want to wrap this data in a class for access. Is it valid to say,
class Foo {
private:
some_type _val;
public:
inline void doSomething() { c_doSomething(&_val); }
}
Foo *x = reinterpret_cast<Foo *>(&a);
x->double();
The class has no virtual functions, and only includes a single data item of the type I'm trying to wrap. Does the C++ standard specify that this reinterpret_cast is safe and valid? sizeof(Foo) == sizeof(some_type), no address alignment issues, or anything? (In my case, I'd be ensuring that some_type is either a primitive type like int, or a POD structure, but I'm curious what happens if we don't enforce that restriction, too - for example, a derived class of a UIWidget like a UIMenuItem, or something.)
Thanks!
Is it valid to say...
No, this is not valid. There are only a small number of types that a can be treated as; the complete list can be found in an answer I gave to another question.
Does the C++ standard specify that this reinterpret_cast is safe and valid?
The C++ Standards says very little about reinterpret_cast. Its behavior is almost entirely implementation-defined, so use of it is usually non-portable.
The correct way to do this would be to either
have a Foo constructor that takes a some_type argument and makes a copy of it or stores a reference or pointer to it, or
implement your "wrapper" interface as a set of non-member functions that take a some_type object by reference as an argument.
14882/1998/9.2.17:
"A pointer to a PODstruct
object, suitably converted using a reinterpret_cast, points to its initial
member (or if that member is a bitfield,
then to the unit in which it resides) and vice versa. [Note: There
might therefore be unnamed padding within a PODstruct
object, but not at its beginning, as necessary to
achieve appropriate alignment. ]"
So, it would be valid if your wrapper was strictly a POD in itself. However, access specifiers mean that it is not a strictly a POD. That said, I would be interested in knowing whether any current implementation changes object layout due to access specifiers. I think that for all practical purposes, you are good to go.
And for the case when the element is not a POD, it follows that the container is not a POD, and hence all bets are off.
Since your Foo object is already only valid as long as the existing a is valid:
struct Foo {
some_type &base;
Foo(some_type &base) : base (base) {}
void doSomething() { c_doSomething(&base); }
}
//...
Foo x = a;
x.doSomething();
You want to look up the rules governing POD (plain old data) types. If the C++ class is a POD type, then yes, you can cast it.
The details of what actually happens and how aliasing is handled are implementation defined, but are usually reasonable and should match what would happen with a similar C type or struct.
I happen to use this a lot in a project of mine that implements B+ trees in shared memory maps. It has worked in GCC across multiple types of Linux and BSDs including Mac OS X. It also works fine in Windows with MSVC.
Yes, this is valid as long as the wrapper type you are creating (Foo in your example) is a POD-type.
Is it possible to write a C++ class or struct that is fully compatible with C struct. From compatibility I mean size of the object and memory locations of the variables. I know that its evil to use *(point*)&pnt or even (float*)&pnt (on a different case where variables are floats) but consider that its really required for the performance sake. Its not logical to use regular type casting operator million times per second.
Take this example
Class Point {
long x,y;
Point(long x, long y) {
this->x=x;
this->y=y;
}
float Distance(Point &point) {
return ....;
}
};
C version is a POD struct
struct point {
long x,y;
};
The cleanest was to do this is to inherit from the C struct:
struct point
{
long x, y;
};
class Point : public struct point
{
public:
Point(long x, long y)
{ this->x=x; this->y=y; }
float Distance(Point &point)
{ return ....; }
}
The C++ compiler guarantees the C style struct point has the same layout as with the C compiler. The C++ class Point inherits this layout for its base class portion (and since it adds no data or virtual members, it will have the same layout). A pointer to class Point will be converted to a pointer to struct point without a cast, since conversion to a base class pointer is always supported. So, you can use class Point objects and freely pass pointers to them to C functions expecting a pointer to struct point.
Of course, if there is already a C header file defining struct point, then you can just include this instead of repeating the definition.
Yes.
Use the same types in the same order in both languages
Make sure the class doesn't have anything virtual in it (so you don't get a vtable pointer stuck on the front)
Depending on the compilers used you may need to adjust the structure packing (usually with pragmas) to ensure compatibility.
(edit)
Also, you must take care to check the sizeof() the types with your compilers. For example, I've encountered a compiler that stored shorts as 32 bit values (when most will use 16). A more common case is that an int will usually be 32 bits on a 32-bit architecture and 64 bits on a 64-bit architecture.
POD applies to C++. You can have member functions. "A POD type in C++ is an aggregate class that contains only POD types as members, has no user-defined destructor, no user-defined copy assignment operator, and no nonstatic members of pointer-to-member type"
You should design your POD data structures so they have natural alignment, and then they can be passed between programs created by different compilers on different architectures. Natural alignment is where the memory offset of any member is divisible by the size of that member. IE: a float is located at an address that is divisible by 4, a double is on an address divisible by 8. If you declare a char followed by a float, most architectures will pad 3 bytes, but some could conceivably pad 1 byte. If you declare a float followed by a char, all compilers (I ought to add a source for this claim, sorry) will not pad at all.
C and C++ are different languages but it has always been the C++'s intention that you can have an implementation that supports both languages in a binary compatible fashion. Because they are different languages it is always a compiler implementation detail whether this is actually supported. Typically vendors who supply both a C and C++ compiler (or a single compiler with two modes) do support full compatibility for passing POD-structs (and pointers to POD-structs) between C++ code and C code.
Often, merely having a user-defined constructor breaks the guarantee although sometimes you can pass a pointer to such an object to a C function expecting a pointer to a struct with and identical data structure and it will work.
In short: check your compiler documentation.
Use the same "struct" in both C and C++. If you want to add methods in the C++ implementation, you can inherit the struct and the size should be the same as long as you don't add data members or virtual functions.
Be aware that if you have an empty struct or data members that are empty structs, they are different sizes in C and C++. In C, sizeof(empty-struct) == 0 although in C99, empty-structs are not supposed to be allowed (but may be supported anyway as a "compiler extension"). In C++, sizeof(empty-struct) != 0 (typical value is 1).
In addition to other answers, I would be sure not to put any access specifiers (public:, private: etc) into your C++ class / struct. IIRC the compiler is allowed to reorder blocks of member variables according to visibility, so that private: int a; pubic: int b; might get a and b swapped round. See eg this link: http://www.embedded.com/design/218600150?printable=true
I admit to being baffled as to why the definition of POD does not include a prohibition to this effect.
As long as your class doesn't exhibit some advanced traits of its kind, like growing something virtual, it should be pretty much the same struct.
Besides, you can change Class (which is invalid due to capitalization, anyway) to struct without doing any harm. Except for the members will turn public (they are private now).
But now that I think of your talking about type conversion… There's no way you can turn float into long representing the same value or vice versa by casting pointer type. I hope you only want it these pointers for the sake of moving stuff around.
Is there a side effect in doing this:
C code:
struct foo {
int k;
};
int ret_foo(const struct foo* f){
return f.k;
}
C++ code:
class bar : public foo {
int my_bar() {
return ret_foo( (foo)this );
}
};
There's an extern "C" around the C++ code and each code is inside its own compilation unit.
Is this portable across compilers?
This is entirely legal. In C++, classes and structs are identical concepts, with the exception that all struct members are public by default. That's the only difference. So asking whether you can extend a struct is no different than asking if you can extend a class.
There is one caveat here. There is no guarantee of layout consistency from compiler to compiler. So if you compile your C code with a different compiler than your C++ code, you may run into problems related to member layout (padding especially). This can even occur when using C and C++ compilers from the same vendor.
I have had this happen with gcc and g++. I worked on a project which used several large structs. Unfortunately, g++ packed the structs significantly looser than gcc, which caused significant problems sharing objects between C and C++ code. We eventually had to manually set packing and insert padding to make the C and C++ code treat the structs the same. Note however, that this problem can occur regardless of subclassing. In fact we weren't subclassing the C struct in this case.
I certainly not recommend using such weird subclassing. It would be better to change your design to use composition instead of inheritance.
Just make one member
foo* m_pfoo;
in the bar class and it will do the same job.
Other thing you can do is to make one more class FooWrapper, containing the structure in itself with the corresponding getter method. Then you can subclass the wrapper. This way the problem with the virtual destructor is gone.
“Never derive from concrete classes.” — Sutter
“Make non-leaf classes abstract.” — Meyers
It’s simply wrong to subclass non-interface classes. You should refactor your libraries.
Technically, you can do what you want, so long as you don’t invoke undefined behavior by, e. g., deleting a pointer to the derived class by a pointer to its base class subobject. You don’t even need extern "C" for the C++ code. Yes, it’s portable. But it’s poor design.
This is perfectly legal, though it might be confusing for other programmers.
You can use inheritance to extend C-structs with methods and constructors.
Sample :
struct POINT { int x, y; }
class CPoint : POINT
{
public:
CPoint( int x_, int y_ ) { x = x_; y = y_; }
const CPoint& operator+=( const POINT& op2 )
{ x += op2.x; y += op2.y; return *this; }
// etc.
};
Extending structs might be "more" evil, but is not something you are forbidden to do.
Wow, that's evil.
Is this portable across compilers?
Most definitely not. Consider the following:
foo* x = new bar();
delete x;
In order for this to work, foo's destructor must be virtual which it clearly isn't. As long as you don't use new and as long as the derived objectd don't have custom destructors, though, you could be lucky.
/EDIT: On the other hand, if the code is only used as in the question, inheritance has no advantage over composition. Just follow the advice given by m_pGladiator.
This is perfectly legal, and you can see it in practice with the MFC CRect and CPoint classes. CPoint derives from POINT (defined in windef.h), and CRect derives from RECT. You are simply decorating an object with member functions. As long as you don't extend the object with more data, you're fine. In fact, if you have a complex C struct that is a pain to default-initialize, extending it with a class that contains a default constructor is an easy way to deal with that issue.
Even if you do this:
foo *pFoo = new bar;
delete pFoo;
then you're fine, since your constructor and destructor are trivial, and you haven't allocated any extra memory.
You also don't have to wrap your C++ object with 'extern "C"', since you're not actually passing a C++ type to the C functions.
I don't think it is necessarily a problem. The behaviour is well defined, and as long as you are careful with life-time issues (don't mix and match allocations between the C++ and C code) will do what you want. It should be perfectly portable across compilers.
The problem with destructors is real, but applies any time the base class destructor isn't virtual not just for C structs. It is something you need to be aware of but doesn't preclude using this pattern.
It will work, and portably BUT you cannot use any virtual functions (which includes destructors).
I would recommend that instead of doing this you have Bar contain a Foo.
class Bar
{
private:
Foo mFoo;
};
I don't get why you don't simply make ret_foo a member method. Your current way makes your code awfully hard to understand. What is so difficult about using a real class in the first place with a member variable and get/set methods?
I know it's possible to subclass structs in C++, but the danger is that others won't be able to understand what you coded because it's so seldom that somebody actually does it. I'd go for a robust and common solution instead.
It probably will work but I do not believe it is guaranteed to. The following is a quote from ISO C++ 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.
It's hard to see how in the "real world" this could actually be the case.
EDIT:
The bottom line is that the standard has not limited the number of places where a base class subobject layout can be different from a concrete object with that same Base type. The result is that any assumptions you may have, such as POD-ness etc. are not necessarily true for the base class subobject.
EDIT:
An alternative approach, and one whose behaviour is well defined is to make 'foo' a member of 'bar' and to provide a conversion operator where it's necessary.
class bar {
public:
int my_bar() {
return ret_foo( foo_ );
}
//
// This allows a 'bar' to be used where a 'foo' is expected
inline operator foo& () {
return foo_;
}
private:
foo foo_;
};