tags:

views:

103

answers:

2

Consider this example:

#include <iostream>

class myclass
{
public:
    void print() { std::cout << "myclass"; }
};

int main()
{
    myclass* p = 0x0; // any address

    p->print(); // prints "myclass"
}

I didn't call the member function print through an object of type myclass. Instead I called it from a pointer to a random place in memory. Is this a defined behavior? That is, is the member function guaranteed to be executed before the creation of any object of type myclass?

+11  A: 

Dereferencing a null (0) pointer is invoking undefined behaviour. The program can do anything it likes, including work as expected.

In part, you get away with it here because the print() member function does not reference any member variables (there aren't any), but the compiler could still have generated code that would crash on you. And if the member function did reference any member variables, you would be severely into undefined behaviour. It probably isn't worth trying to work out the extent of the what you can do because you are invoking undefined behaviour, which can vary from compiler to compiler, version to version, platform to platform, run to run.

Jonathan Leffler
Thanks. can we say that the compiler is free to eliminate an unused class as a whole if it isn't used in some code?
AraK
That's a somewhat separate question, but yes, I think that the optimizer could eliminate an unused class if it can demonstrate that the code cannot be used. Demonstrating that something is not used is tough, though - consider that you might dynamically load a shared library that tries to reference something that appeared to be unused and was optimized away. It probably constitutes bad design, but the compiler isn't supposed to break code just because it is badly designed (though it would be doing the world a great favour if it could/did!).
Jonathan Leffler
+1, but I would also add that if print() was virtual you would get even more severely undefined behaviour!
Nic Strong
@Jonathan Thanks a lot. great explanation in your comment also :)
AraK
+2  A: 

You may find that changing your print() function may help enlighten the situation:

void print() { std::cout << "myclass, this=" << this; }

This outputs the value of the C++ this pointer, which in your example will be 0 (or whatever you set p to). Accessing any data member of the class will be the same as dereferencing this, which if it doesn't point to a validly constructed instance of myclass, leads to undefined behaviour.

You will also run into problems if you declare your function as virtual:

virtual void print() { std::cout << "myclass"; }

That implementation probably won't print anything before crashing. The reason is that the compiler generates code to look at the object vtable when calling a virutal function, to discover which function to actually call. Without a valid object, that is likely to crash.

Greg Hewgill