Dynamic_cast failing - c++

Suppose the code is as such:
#include <iostream>
using namespace std;
class dog
{
public:
virtual ~dog()
{
}
};
class yellowdog : public dog
{
int age;
public:
void bark() { cout << "woof." << endl;}
};
int main()
{
dog *pd = new dog();
yellowdog *py = dynamic_cast<yellowdog*>(pd);
py->bark();
cout << "py = " << py << endl;
cout << "pd = " << pd << endl;
}
Output:
woof.
py = 0x0
pd = 0x7fd4d34000e0
I understand why py = 0. I know that there is a run-time check and in that run-time check, there is a failure to convert dog to yellowdog, hence the value of py = 0.
My question is why py->bark() still can work. Why is that it is still able to print out "woof."?
My apologies to the code before. Do check now..

py is a null pointer, so py->bark() invokes undefined behavior. Anything can happen, including things appearing to work. Unlike Java or C#, C++ has no guarantee of failing immediately if you access a null pointer. In the name of efficiency, C++ compilers will generally elide null pointer checks.
As it happens, bark() does not use this at all, so it is not surprising that it would work okay. You should not rely on it—there is no guarantee that it will work—but it's not surprising.

Two reasons the casting fails:
You're casting a pointer to a non-pointer type, and then assigning this to a pointer. This should give you compiler errors.
pd is a pointer to dog and not a yellowdog, so no downcast is possible, and py would be a null pointer (and dereferencing this leads to undefined behavior).
It the undefined behavior from the second point that is giving you trouble. Undefined behavior is, by its very definition, undefined, and anything can happen. From crashes, to things seemingly working, to the appearance of nasal demons.

It doesn't really work: calling a method from a null pointer is undefined behavior. The compiler can decide whether to crash the program, have it work anyway if the method doesn't use data members (which is what happens in your case), erase all data in your disk or even call SWAT teams at your place. You are lucky nothing bad happens in your case.

What you have done in undefined behaviour but you want to know why it works anyway in your case.
The reason is that the function yellowdog::bark() does not use the this in any way, plus the fact it is inlined into the header means the compiler may well have simply inlined its implementation for you.
In other words, it sees you called bark() on a yellowdog pointer and knows how to implement that, it substitutes the call with cout << "woof." << endl

Related

C++ : unallocated pointer to object can be repeatedly safely dereferenced... why?

why is this code practically reliably working, is not unstable, undefined?
it's dereferencing unallocated, dangling pointers to objects.
thanks.
#include <iostream>
using namespace std;
class Base{
public:
void vf()
{
cout<<"vf\n";
}
void pr(){
cout<<"vb\n";
}
};
int main() {
Base* b ;
//Base * bp = new Base; //trying to disrupt memory
char ar[]= "ttttttttttt"; //trying to disrupt memory
b->pr();
char aa[]= "ttttttttttt";
b->vf();
return 0;
}
Welcome to the Wonderful World of Undefined Behavior! According to the C++ spec, the behavior of this problem is undefined, so what you're seeing might work on your system but crash on others, or vice-versa.
Practically speaking, what's happening here is probably an artifact of how the compiler generates code for member functions. Typically, a member function that looks like this:
void doSomething() {
cout << "Hello!" << endl;
}
would probably be compiled as if it were a free function like this:
void Base_doSomething(Base* this) {
cout << "Hello!" << endl;
}
In that sense, when you write
bf->doSomething();
the compiler treats it as if you've written
Base_doSomething(bf);
and nothing bad happens, because Base_doSomething doesn't reference the this pointer, which is where all the bad things happen.
Now, this is very brittle. If you try to read any of the data members of the Base type, this code will crash because then you are reading from a bad pointer. Similarly, if doSomething were a virtual function, you'd get a crash because calling a virtual function (typically) requires reading from the receiver object to find the vtable to determine which function to call, and a dangling pointer will then lead to a bad memory access.
So, to summarize:
This code leads to undefined behavior, so the particular behavior you're seeing isn't guaranteed to happen or work across platforms.
Although syntactically bp->doSomething() looks like a pointer dereference, it might not actually involve a pointer dereference.
Member functions are typically compiled as free functions that have an "implicit this" pointer passed as a first argument.
Virtual functions work differently than this, so you'd expect to see different behavior there.
Hope this helps!

Method call after invalid C-style cast works

So I'm trying to learn a bit more about the differences between C-style-casts, static_cast, dynamic_cast and I decided to try this example which should reflect the differences between C-style-casts and static_cast pretty good.
class B
{
public:
void hi() { cout << "hello" << endl; }
};
class D: public B {};
class A {};
int main()
{
A* a = new A();
B* b = (B*)a;
b->hi();
}
Well this code snippet should reflect that the C-style-cast goes very wrong and the bad cast is not detected at all. Partially it happens that way. The bad cast is not detected, but I was surprised when the program, instead of crashing at b->hi();, it printed on the screen the word "hello".
Now, why is this happening ? What object was used to call such a method, when there's no B object instantiated ? I'm using g++ to compile.
As others said it is undefined behaviour.
Why it is working though? It is probably because the function call is linked statically, during compile-time (it's not virtual function). The function B::hi() exists so it is called. Try to add variable to class B and use it in function hi(). Then you will see problem (trash value) on the screen:
class B
{
public:
void hi() { cout << "hello, my value is " << x << endl; }
private:
int x = 5;
};
Otherwise you could make function hi() virtual. Then function is linked dynamically, at runtime and program crashes immediately:
class B
{
public:
virtual void hi() { cout << "hello" << endl; }
};
This only works because of the implementation of the hi() method itself, and the peculiar part of the C++ spec called undefined behaviour.
Casting using a C-style cast to an incompatible pointer type is undefined behaviour - literally anything at all could happen.
In this case, the compiler has obviously decided to just trust you, and has decided to believe that b is indeed a valid pointer to an instance of B - this is in fact all a C-style cast will ever do, as they involve no runtime behaviour. When you call hi() on it, the method works because:
It doesn't access any instance variables belonging to B but not A (indeed, it doesn't access any instance variables at all)
It's not virtual, so it doesn't need to be looked up in b's vtable to be called
Therefore it works, but in almost all non-trivial cases such a malformed cast followed by a method call would result in a crash or memory corruption. And you can't rely on this kind of behaviour - undefined doesn't mean it has to be the same every time you run it, either. The compiler is perfectly within its rights with this code to insert a random number generator and, upon generating a 1, start up a complete copy of the original Doom. Keep that firmly in mind whenever anything involving undefined behaviour appears to work, because it might not work tomorrow and you need to treat it like that.
Now, why is this happening ?
Because it can happen. Anything can happen. The behaviour is undefined.
The fact that something unexpected happened demonstrates well why UB is so dangerous. If it always caused a crash, then it would be far easier to deal with.
What object was used to call such a method
Most likely, the compiler blindly trusts you, and assumes that b does point to an object of type B (which it doesn't). It probably would use the pointed memory as if the assumption was true. The member function didn't access any of the memory that belongs to the object, and the behaviour happened to be the same as if there had been an object of correct type.
Being undefined, the behaviour could be completely different. If you try to run the program again, the standard doesn't guarantee that demons won't fly out of your nose.

Strange results with object creation and binding

Mistakenly I wrote something daft, which to my surprise worked.
class A
{ public:
void print()
{
std::cout << "You can't/won't see me !!!" << std::endl;
}
A* get_me_the_current_object()
{
return this;
}
};
int main()
{
A* abc = dynamic_cast<A*>(abc);
abc->print();
}
Here, A* abc = dynamic_cast<A*>(abc), I am doing dynamic_cast on a pointer, which isn't declared. But, it works, so I assumed that the above statement is broken as:
A* abc;
abc = dynamic_cast<A*>(abc);
and therefore, it works. However, on trying some more weird scenarios such as:
A* abc;
abc->print();
and, further
A* abc = abc->get_me_the_current_object();
abc->print();
I was flabbergasted, looking at how these examples worked and the mapping was done.
Can someone please elaborate on how these are working? Thanks in advance.
You've made the common mistake of thinking that undefined behaviour and C++ bugs mean you should expect to see a dramatic crash or your computer catching fire. Sometimes nothing happens. That doesn't mean the code "works", because it's still got a bug, it's just that the symptoms haven't shown up ... yet.
But, it works, so I assumed that the above statement is broken as:
Yes, all you're doing is converting an uninitialized pointer to the same type, i.e. no conversion needed, so the compiler does nothing. Your pointer is still the same type and is still uninitialized.
This is similar to this:
int i = i;
This is valid according to the grammar of C++, because i is in scope at that point, but is undefined because it copies an uninitialized object. It's unlikely to actually set your computer on fire though, it appears to "work".
Can someone please elaborate on how these are working?
Technically you're dereferencing an invalid pointer, which is undefined behaviour, but since your member functions don't actually use any members of the object, the invalid this pointer is not dereferenced, so the code "works" (or at least appears to.)
This is similar to:
void function(A* that)
{
std::cout << "Hello, world!\n";
}
A* p;
function(p);
Because the that pointer is not used (like the this pointer is not used in your member functions) this doesn't necessarily crash, although it might do on implementations where even copying an uninitialized pointer could cause a hardware fault. In your example it seems that your compiler doesn't need to dereference abc to call a non-static member function, and passing it as the hidden this parameter does not cause a hardware fault, but the behaviour is still undefined even though it doesn't fail in an obvious way such as a segfault..
abc is uninitialized and points to an undefined location in memory, but your methods don't read anything from *this so they won't crash.
The fact that they won't crash is almost certainly implementation defined behavior though.

Can NULL pointer after "dynamic_cast" actually be dereferenced?

The following code compiles correctly and get the mysterious output:
special Investment function
00000000
(Environment: C++ VS2010)
#include <iostream>
#include <vector>
using namespace std;
class Security {
public:
virtual ~Security() {}
};
class Stock : public Security {};
class Investment : public Security {
public:
void special() {
cout << "special Investment function" << endl;
}
};
int main() {
Security* p = new Stock;
dynamic_cast<Investment*>(p)->special();
cout << dynamic_cast<Investment*>(p) << endl;
return 0;
}
How could it be? Dereferencing a NULL pointer and get a "correct" output instead of crash?
Is it a special "characteristic" of VS2010?
Now I see. I did a test and it appears that dereferencing "this" in "special" function cause the program to crash.
Thanks for your help.
Dereferencing a null pointer is undefined behavior - you can get unexpected results. See this very similar question.
In this case Investment::special() is called in a non-virtual way, so you can think the compiler just creates a global function
Investment_special_impl( Investment* this )
and calls it passing a null this pointer as the implicit parameter.
You should not rely on this.
This is 'undefined bahviour'. Think of methods as having an implicit parameter, carrying 'this'. In your case, NULL was passed as actual argument for 'this'. Since you did not reference any object data refererenced (implicitly or explicitly) by 'this', it did not crash.
Had the method been virtual, it would most likely have crashed, since virtual calls are often dispatched through a lookup table associated with the object (and as a consequence 'this').
Since compiler writers are free to implement 'this' and virtual member lookup tables as they please, you shouldn't depend on this behaviour. It is undefined.
In most implementations of C++ non-virtual methods don't require a valid instance to be called (it's faster to not check this, since standard doesn't require it).
You can set your pointer to NULL and method will still succeed if you don't access instance fields.
Virtual methods require valid vtable, so they always dereference object and cause error in case it's not initialized.
Nowhere do you dereference a null pointer in here: you simply call the function Investment::special(NULL), which is non-virtual, and in its body does not dereference this. Although the spec probably tells this is undefined behavior, it's perfectly sane from the compiler not to put any dereferencing here, so that the program does not crash.
Dereferencing any NULL pointer is Undefined Behaivor.
You should NOT dereference the NULL pointer as it can cause Undefine Behavior. Why your code is working is because in the method:
void special() {
cout << "special Investment function" << endl;
}
You really don't make any reference to this. To demo that, just declare a variable inside Investment class and try to print it inside special(). You will get a crash.
Dereferencing a null pointer invokes undefined behavior, irrespective of how you get the null pointer, whether as a result of dynamic_cast or something else.
I'm not sure about the dereference NULL question, but the behaviour of the code i can explain.
dynamic_cast< Investment* >(p)->special();
prints: "special Investment function"
cout << dynamic_cast < Investment* >(p) << endl;
prints: "0xABABABA" <- memory address of instance p
It's like running:
cout << p << endl;

static_cast doubt

#include <iostream>
class A
{
public:
A()
{
std::cout << "\n A_Constructor \t" << this <<std::endl;
}
void A_Method()
{
std::cout <<"\n A_Method \t" << this <<std::endl;
}
};
class B:public A
{
public:
B()
{
std::cout <<"\n B_Constructor \n";
}
void B_Method()
{
std::cout <<"\n B_Method \t" << this <<std::endl;
}
};
int main()
{
A *a_obj = new A;
B *b_obj = static_cast<B*> (a_obj); // This isn't safe.
b_obj->B_Method();
getchar();
return 0;
}
OUTPUT :
A_Constructor 001C4890
B_Method 001C4890
As no run-time check isn't involved in type conversion, static_cast isn't safe. But in this example, I got what I didn't even expect. Since there is no call to B::B(), any of it's members should not be able to get called by b_obj. Despite that I got the output.
In this simple case, I might have succeeded though it is known unsafe. My doubts are -
Though there is no call to B::B(), how was I able to access class B member functions.
Can some one please provide an example, where this is unsafe and might get wrong( though what I given before might serve as a bad example, but even better).
I did it on Visual Studio 2010 and with \Wall option set.
This is Undefined Behavior. Sometimes UB causes crashes. Sometimes it seems to "work". You are right that you shouldn't do this, even though in this case less bad things happened.
What you are trying is undefined behaviour so ANYTHING could happen. This seems to work (and probably works) fine as you don't try to access any data members (you don't have any). Try to add some data members to both classes and access it from methods, you will see that behaviour will change to completely unpredictable.
I doubt that this particular case is UB. First, it just casts a pointer from one type to another. Since there is no virtual/multiple inheritance involved, no pointer adjustment is performed, so basically the pointer value stays the same. Surely it points to an object of a wrong type, but who cares, as long as we don't access any B members, even if there were some? And even if there was pointer adjustment involved, it would still be okay if we didn't access any memory pointed by it, which we don't.
Then, the example calls a method of B. Since it is not virtual, it just a normal function call with the hidden argument this (think B::B_Method(this)). Now, this points to an object of a wrong type, but again, who cares? The only thing it does is print it, which is always a safe thing to do.
In fact, you can even call methods using a NULL pointer. It works as long as the method isn't virtual and doesn't try to access anything pointed by this. I once had a library used by many programs. This library had a singleton-like class which had to be constructed explicitly, but none of the programs actually did it. The instance pointer was initialized to NULL by default, as it was global. It worked perfectly since the class had no data members at all. Then I added some and all the programs suddenly started to crash. When I found out the reason, I had a really good laugh. I've been using an object that didn't even exist.