Why does this code only print 42? - c++

Could somebody please explain to me why does this code only print "42" instead of "created\n42"?
#include <iostream>
#include <string>
#include <memory>
using namespace std;
class MyClass
{
public:
MyClass() {cout<<"created"<<endl;};
int solution() {return 42;}
virtual ~MyClass() {};
};
int main(int argc, char *argv[])
{
auto_ptr<MyClass> ptr;
cout<<ptr->solution()<<endl;
return 0;
}
BTW I tried this code with different values in solution and I always get the "right" value, so it doesn't seem to be a random lucky value.

Because it exhibits undefined behaviour - you dereference a null pointer.
When you say:
auto_ptr<MyClass> ptr;
you create an autopointer which doesn't point to anything. This is equivalent to saying:
MyClass * ptr = NULL;
Then when you say:
cout<<ptr->solution()<<endl;
you dereference this null pointer. Doing that is undefined in C++ - for your implementation, it appears to work.

std::auto_ptr will not automatically create an object for you. That is, ptr in main as it stands is initialized to null. Dereferencing this is undefined behavior, and you just happen to be getting lucky and getting 42 as a result.
If you actually create the the object:
int main(int argc, char *argv[])
{
auto_ptr<MyClass> ptr(new MyClass);
cout << ptr->solution() << endl;
return 0;
}
You will get the output you expect.

First, keep in mind that the -> operator of auto_ptr is essentially forwarded on to the contained pointer. So for this discussion, your code in main becomes equivalent to:
MyClass* ptr = NULL;
cout << ptr->solution() << endl;
Then note that compilers tend to implement member functions in ways that act very much as if they were non-member functions with the this pointer passed as another function argument. So from your current compiler's point of view, your code in main acts as if it was:
MyClass* ptr = NULL;
cout << solution(ptr) << endl;
with solution written as:
int solution(MyClass* this) { return 42; }
In which case it becomes obvious why there wasn't a crash.
However as others have already mentioned, these are internal details of how compilers implement C++, which are not specified by the language standard. So in theory this code could work as described here on one compiler but crash or do something else entirely on another compiler.
But in practice, even if the standard doesn't guarantee this behavior, any particular compiler could guarantee it if they want to. For instance: since MFC relies on this behavior, it is very unlikely that Visual Studio will ever stop supporting it. Of course, you would have to research each particular compiler where your code might be used to make sure that they actually guarantee this behavior.

Because you don't know the question to the answer xD
It seems you're not calling the constructor, right?

You a re not creating an instance of the object.
You are only creating a smart pointer.
When you call the method you are de-referencing a NULL pointer, so as Neil mentioned you are now in undefined behavior. But since your code does not try and access any member variables it luckily does not crash.
Try this:
auto_ptr<MyClass> ptr(new MyClass);

Because ptr is uninitialized and you're lucky. You should first call new for it:
auto_ptr<MyClass> ptr( new MyClass );

You're not getting a crash because the "solution" method doesn't need to actually use the class members. If you were returning a member or something, you'd probably get a crash.

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!

Why does this smart pointer give the correct result when its target should have been deleted?

Disclaimer: I know this is not how unique_ptr should be used, but for the sake of understanding, I would like to know what is going on here. Thank you!
Consider this function:
void foo(int* a) {
unique_ptr<int> pointer_in_function(a);
}
And this main function:
int main(void) {
int* myInt = new int(5);
unique_ptr<int> pointer_in_main(myInt);
foo(myInt);
cout << *pointer_in_main << endl;
cout << *pointer_in_main << endl;
cin.get();
return 0;
}
I consistently get the correct answer from the first cout. The second is undefined. The program sometimes crashes with a critical error on exit, but not always.
What I do not understand is why the first cout gives the correct answer consistently. Shouldn't the integer pointed to by myInt have been deleted when pointer_in_function went out of scope? Thank you for your help!
edit: As an aside, just to be sure, am I correct in my assumption that calling foo should delete my integer because pointer_in_function goes out of scope?
What I do not understand is why the first cout gives the correct answer consistently.
Most implementations do not clear memory after deleting or return it back to the OS, so if you inspect the memory quickly after deleting, the chances of it not having been overwritten yet are higher.
That's one of the valid consequences of undefined behaviour. It may be 100% predictable on your particular implementation, though it need not behave the same on others.
It's not a good way to do (pure enough) experiments with constructors / destructors or deletion. If you have an object uncorrupted it DOESN'T imply that a delete operator hasn't been called (as its effect to the memory data is undefined and indeed many memory manager implementations don't change the released memory content immediately). Instead, create a class with explicit constructor(s) and destructor reporting their invocation and use it in place of int. As a destructor call prepends an object deletion (and as your code doesn't use stack or static allocation of an object under test, a destructor call is always implies a deletion), you may use destructor calls to trace deletions. Something like:
#include <iostream>
class MyObj {
int value;
MyObj(int v) : value(v) {std::cerr << "MyObj ctor called"<<std::endl;}
~MyObj() {std::cerr << "MyObj dtor called"<<std::endl;}
};
.....
int main (int argc, char **argv) {
MyObj* myInt = new MyObj(5);
....
}

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.

Checking for a null reference?

Lets say you have something like this:
int& refint;
int* foo =0;
refint = *foo;
How could you verify if the reference is NULL to avoid a crash?
You can't late-initialize a reference like that. It has to be initialized when it's declared.
On Visual C++ I get
error C2530: 'refint' : references
must be initialized
with your code.
If you 'fix' the code, the crash (strictly, undefined behaviour) happens at reference usage time in VC++ v10.
int* foo = 0;
int& refint(*foo);
int i(refint); // access violation here
The way to make this safe is to check the pointer at reference initialization or assignment time.
int* foo =0;
if (foo)
{
int& refint(*foo);
int i(refint);
}
though that still does not guarantee foo points to usable memory, nor that it remains so while the reference is in scope.
You don't, by the time you have a "null" reference you already have undefined behaviour. You should always check whether a pointer is null before trying to form a reference by dereferencing the pointer.
(Your code is illegal; you can't create an uninitialized reference and try and bind it by assigning it; you can only bind it during initialization.)
In general, you can't.
Whoever "creates a null reference" (or tries to, I should say) has already invoked undefined behavior, so the code might (or might not) crash before you get a chance to check anything.
Whoever created the reference should have done:
int *foo = 0;
if (foo) {
int &refint = *foo;
... use refint for something ...
}
Normally it's considered the caller's problem if they've written *foo when foo is null, and it's not one function's responsibility to check for that kind of error in the code of other functions. But you could litter things like assert(&refint); through your code. They might help catch errors made by your callers, since after all for any function you write there's a reasonable chance the caller is yourself.
All the answers above are correct, but if for some reason you want to do this I thought at least one person should provide an answer. I am currently trying to track down a bad reference in some source code and it would be useful to see if someone has deleted this reference and set it to null at some point. Hopefully this wont generate to many down votes.
#include <iostream>
int main()
{
int* foo = nullptr;
int& refint = *foo;
if(&refint == nullptr)
std::cout << "Null" << std::endl;
else
std::cout << "Value " << refint << std::endl;
}
Output:
Null
To make the above code compile, you will have to switch the order:
int* foo =0;
int& refint = *foo; // on actual PCs, this code will crash here
(There may be older processor or runtime architectures where this worked.)
....saying all of the above, if you do want to have a null reference, use boost::optional<>, works like a charm..
You don't need to, references cannot be null.
Read the manual.

Why am I able to make a function call using an invalid class pointer

In below code snippet, although pointer is not initialized the call is still made successfully
temp *ptr;
ptr->func2();
Is it due to C++ language property, or it is VC++6 compiler which is foul playing?
class temp {
public:
temp():a(9){}
int& func1()
{
return a;
}
bool func2(int arg)
{
if(arg%2==0)
return true;
return false;
}
int a;
};
int main(int argc, char **argv)
{
temp *ptr;
int a;
cin>>a;
if(ptr->func2(a))
{
cout<<"Good poniner"<<endl;
}
ptr->func1(); // Does not crash here
int crashere=ptr->func1();// But does crash here
return 0;
}
The C++ compiler doesn't prevent you from using uninitialised pointers, and although the results are undefined, it's normal for compilers in the real world to generate code that ignores the fact that the pointer is uninitialised.
It's one of the reasons why C++ is both fast and (comparatively) dangerous relative to some other languages.
The reason your call to func2 succeeds is that it doesn't touch its this pointer. The pointer value is never used, so it can't cause a problem. In func1 you do use the this pointer (to access a member variable), which is why that one crashes.
This is entirely compiler-dependent and undefined behaviour according to the standard. You shouldn't rely on this.
Call to func2() succeeds because the exact method to call is known at compile time (the call is not virtual) and the method itself doesn't dereference this pointer. So invalid this is okay.
ptr->func1(); // This works
because the compiler is instructed to return the reference to the class member. To do so it simply adds the offset of the member to the invalid value of this pointer and that produces yet another invalid pointer (reference, which is almost the same).
int crashere=ptr->func1();// Crashes here
because now the compiler is instructed to retrieve the value via that invalid reference and this crashed the program.
C++ has the notion of Undefined Behavior. Using an uninitialized pointer is a common example of such Undefined Behavior. For performance reasons, the C++ standard places no restrictions whatsoever on the possible outcome. That is to say, formatting the harddisk is perfectly acceptable.
I suspect that ptr->func2() is optimised away as it always returns true. But as Richie says, the use of the pointer is fine in this case as you;re not touching any instance data (a) and as such there is nothing to crash into.
Its not working. Its just by luck that your application is not crashing where your expecting it to crash. Its not a feature but a side-effect of the compiler which is allowing the function call to seem to work.
You can call the methods using uninitialised pointers. It will work either
ptr->func1();
or
int crashere=ptr->func1();//