You're not using any member variables of A the function is completely independent of the A instance, and therefore the generated code happens to not contain anything that dereferences 0. This is still undefined behavior it just may happen to work on some compilers. Undefined behavior means "anything can happen" - including that the program happens to work as the programmer expected.
You're not using any member variables of A - the function is completely independent of the A instance, and therefore the generated code happens to not contain anything that dereferences 0. This is still undefined behavior - it just may happen to work on some compilers. Undefined behavior means "anything can happen" - including that the program happens to work as the programmer expected.
If you e.g. Make mprint virtual you may get a crash - or you may not get one if the compiler sees that it doesn't really need a vtable. If you add a member variable to A and print this, you will get a crash.
1, but ...well, I bet it'll work on almost all compilers - after all, they tend to avoid inserting useless dereferences simply for performance reasons. Still, it's obviously unwise to rely on it. – Eamon Nerbonne Mar 25 '11 at 10:54 @Eamon Nerbonne: Depends what you mean by almost all compilers.
– Loki Astari Mar 25 '11 at 11:04 1 @Martin: are you aware of any compiler where it doesn't? Normally when people say "almost all compilers", it means something like, "I can't think of any good reason for a compiler to do otherwise, nor have I seen a compiler do otherwise, but the standard doesn't require it". If there are exceptions to the rule, it may be that simple cases work everywhere, but then some compiler catches you out with an optimization in a more complicated case.
For example, put if (this == 0) in mprint, see if your favourite compiler still prints with optimization on. – Steve Jessop Mar 25 '11 at 11:42 @Steve Jessop: Actually I am. I was working for a SOC company (a few years ago) and the chip had 8 address registers.
The first 4 normal plain address registers the last 4 started a pre-load of memory into the local cache as soon as they were loaded (the idea being you put the address of an objects in a4-a8 and by the time you accessed a member the data was already in the cache). Normally the this pointer is pushed into a4, In this situation you are potentially going BANG! – Loki Astari Mar 25 '11 at 17:04 @Martin: Excellent, so "they tend to avoid inserting useless dereferences simply for performance reasons" is reversed in that case - it inserts a useless deference to improve performance.
– Steve Jessop Mar 25 '117 at 12:32.
According to the C++ spec, This program has undefined behavior because you're invoking a member function on a null receiver. The reason that this works, though, is that non virtual member functions are typically implemented as regular functions that take the "this" pointer as an implicit first argument. Consequently, if you call a member function on a null pointer, as long as you don't use the this pointer, your program will not crash.
Of course, you cannot rely n this; a valid C++ compiler could cause this to crash. However, virtual functions are a different story because the function that actually gets called needs to be resolved at runtime. This usually involves introspecting on the receiver's virtual function table.
Thus if you try calling a virtual member function on a null pointer, even if te function doesn't access this, it will still cause a crash. Try this out if you're curious!
The results of calling a member function using a null pointer to an object is undefined behavour in c++ so it can do anything. In this case it's likely because it's rewritten your function as it it was like this void mprint(A* this); and your call like this mprint(0); So it's just called it as if it was an ordinary function and passed the null pointer as a parameter which you never then actually use in any way. That explains why it doesn't crash, but the compiler is free to do pretty much anything.
I like this answer, because many people imagine that the functions are included in the instance (and not in the class). And therefor they're worried about excessive memory use... I'd say member functions are just syntaxic sugar for your example. – Tristram Gräbener Mar 25 '11 at 10:57.
Simple Answer: Because mprint() is not using any of the member variables of the class Detailed Answer: When a method of a class is called, class instance is passed on to the callee function (normally as the first argument, however, in some calling conventions such as __thiscall, this is passed in a register). This class instance is used to access all the member variables that are used in the callee method. In this case, this instance is NULL but this doesn't make any difference since no member variables are being used in the callee method.
Try changing your code such that you print the value of a member variable in mprint() method and you will get the crash.
I am not a C++ guy, but you are calling the method on a NULL reference and the method is not static. Is this how C++ works? It allows you to call non-static member method on NULL reference?
Just curious, thanks! – Jan Zyka Mar 25 '11 at 10:53 it's undefined behavour I believe that will likely "work" as you expect in most compilers due to the obvious way to implement it. – JohnB Mar 25 '11 at 10:54 @JanZyka: As Erik's answer says: it is undefined behavior.
Which in this particular case happens to "work normally". – Jon Mar 25 '11 at 10:54 @Jan: Such a method which doesn't use any member variable is a good candidate to be a static method. Remember that data members always have separate copies for every instance of the class but functions have only one copy that is general purpose for every instance.
And can be called directly even. C++, unlike some other languages doesn't impose compile time restrictions on calling method in this way. – Aamir Mar 25 '11 at 10:56 1 @Jan Zyka: One more small thing..its a not a NULL reference, its a NULL pointer – Naveen Mar 25 '11 at 10:56.
Being able of invoking non-virtual member functions on non-valid pointers even enables encoding the information associated to an object in the pointer itself. For example: #include class MagicInteger { public: static MagicInteger* fromInt (int x) { return reinterpret_cast(x); } int getValue() { return static_cast(reinterpret_cast(this)); } private: // forbid messing around MagicInteger (); MagicInteger (MagicInteger&); MagicInteger& operator=(const MagicInteger&); }; int main (void) { MagicInteger* I = MagicInteger::fromInt(6); std::cout getValue().
Don't do this. If you need to be able to store either a pointer or a value, use a union. – Ben Voigt Mar 26 '11 at 20:27 @Ben agreed that this is not a good coding practice.In V8, however, they have a class hierarchy in which class Object is the root.
They maintain a list of Object* that are actually tagged. Class Smiwhich implements the trick I mentioned, inherits from Object, so they are not able to use a union directly. – ncasas Mar 26 '11 at 20:53 @ncasas: Something else must be going on.
This wouldn't work alongside polymorphism, virtual calls would just fail. So the code iterating the list of Object* must be aware of the trick. But then you can have a list of union { Object*; int; } instead.
– Ben Voigt Mar 26 '11 at 21:07 @Ben you're completely right, there's no polymorphism and the code is aware of the trick. However, they aim at packing together the union of the Object* (30 bits due to forced alignment) and the integer (31 bit), plus the discriminator for distinguishing the actual contents (1 bit). If they used a union, they wouldn't be able to fit everything in 32 bits.
– ncasas Mar 26 '11 at 23:48 @ncasas: How would a union prevent things from fitting? The whole point of a union is that the different members share storage. – Ben Voigt Mar 26 '11 at 23:52.
This is completely legal call. Lets understand how it works when a new object is creates its member variables are created. What about member functions?
Member function are not allocated news there is always one copy of all member function. By default a member variable is added to every member function that is this pointer which is pointing to the object itself. When there is no object present that is object pointer is null value.It doenst matter because you are not accesssing it any way.
You will get in problems if you use this pointer of any of the member variable in the method. This is because member variable are not valid in case of null pointer.In MFC we have GetSafeHwnd() method for CWnd. This works on same principle.
1 No, it's not "legal". It's undefined behavior. MFC gets away with it only because MFC is locked to a particular compiler which makes stronger guarantees than the C++ language itself.
– Ben Voigt Mar 26 '11 at 23:56.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.