1
class Foo
{
public:
    Foo(int i)
    {
        _i = i;
    }
    void p()
    {
        cout<<"printed"<<endl;
    }
    int _i;
};
int main()
{
    Foo *p = 0;
    cout <<p<<endl;
    p->p();

    return 0;
}

The actual output of above code is

0
printed

As per my understanding it should give SEG fault for accessing 0x0 addess. Because the *p address is 0x0.

Why it is working ?anybody explain it ?

Rajesh Gopu
  • 863
  • 9
  • 33
  • 5
    This is [*Undefined Behaviour*](https://en.wikipedia.org/wiki/Undefined_behavior). Anything can happen, up to and including *appearing* to work. In this case, if you really want to see a crash, try having a member variable in `Foo`, which you print in `Foo::p()`, to actually force the computer to try to access some memory at the invalid address. – BoBTFish Mar 15 '17 at 10:51
  • Dereferencing a null pointer is always undefined behavior. *However*, you're "just" calling a member function, and for that the compiler doesn't actually dereference the pointer, it just jumps to some code. It would be a very different matter if you used `this` inside the function (for example to print the value of `_i`). – Some programmer dude Mar 15 '17 at 10:51
  • Because in truth `*p` isn't dereferenced anywhere. A method of a class has an hidden parameter containing the `this`, so your call is translated to `methodp(pointerp)`; no dereferencing. Note that if `methodp` was `virtual`, then you surely would have gotten a crash – xanatos Mar 15 '17 at 10:51
  • When you invoke Undefined Behavior as you did, your program is free from any semantic guarantees of the C++ language. – WhiZTiM Mar 15 '17 at 10:51
  • 4
    If you *really want* to increase your odds of a fault, add `<< _i` to your output in `p()`. Regardless, you're invoking *undefined behavior*. Consider yourself *unlucky* it didn't crash when you expected it to. – WhozCraig Mar 15 '17 at 10:53

2 Answers2

4

It is not valid. But undefined beheviour doesn't guarantee segfaults or anything.

You can't rely on anything here, so don't do it. It can (appear to) work, it can crash, it can burn your computer, anything.

In this particular case, the method p() does not depend on anything else in its class, and the compiler is allowed to assume that you have no UB in your code, so it most likely just executes p without even doing anything with the pointer (but again, there is no guarantee that the compiler is working like that).

deviantfan
  • 11,268
  • 3
  • 32
  • 49
  • it can't burn your computer – user Mar 15 '17 at 10:52
  • @user Sure it can. It can even kill people (and did that already). – deviantfan Mar 15 '17 at 10:53
  • I wouldn't say "it can work", because there is no correct behaviour defined. Logically, it can't work. – davmac Mar 15 '17 at 10:53
  • it can't make ETs invade the earth either – user Mar 15 '17 at 10:53
  • I would change "it can work" to "it can seem to work" – zoska Mar 15 '17 at 10:54
  • @user ...but it can make demons come out of your nose. Yeah, we won't get alien invasions. Are you satisfied now? – deviantfan Mar 15 '17 at 10:54
  • Can you also provide reference that this specific case will lead to undefined behavior? I am very curious! – javaLover Mar 15 '17 at 10:55
  • Still there is no response to *Why it is working*? There is an explanation about why this UB is often implemented in that way. – xanatos Mar 15 '17 at 10:55
  • @xanatos It's working because the compilers understand what you are trying to do. Again, undefined behaviour means that the compilers are allowed to do anything, including what the programmer intended. – Aziuth Mar 15 '17 at 10:58
  • 1
    @Aziuth No, it is working because the `*p` isn't dereferenced. The compiler isn't "understanding" anything. There could be 1,000,000 reasons why the compiler could choose to dereference `*p` (for example for security checking, or for logging, or ???), but often compilers won't do it unless it is requested by the program or the function is virtual. – xanatos Mar 15 '17 at 10:59
  • @xanatos You are speaking of this behaviour as far too certain, as if this was how it has to be done in any case. What you describe is what a compiler *might* do. A compiler could also be programmed to dereference anyway in this case. Inefficient, granted, but valid. And yes, "understanding" is the right word here. – Aziuth Mar 15 '17 at 11:06
  • @Aziuth My point on your response was that by using the verb "understand" you imply that this case happened because the compiler did something "active" to make it happen. On the opposite, it happened because the compiler (and the runtime, because pointer dereferencing is done at runtime) did nothing, so for a chain of fate the code ran without apparent problems. – xanatos Mar 15 '17 at 11:11
  • One example of what a compiler can do with this kind of shenanigans: http://stackoverflow.com/questions/36893251/why-does-the-enhanced-gcc-6-optimizer-break-practical-c-code – T.C. Mar 15 '17 at 18:49
-5

Because p() is a normal method (i.e. not virtual), the call to p->p() can be resolved at compile time, and since you don't access any members of p a valid this pointer is not needed inside the method.

Edit: .. but as mentioned above, this is actually undefined behaviour.

Gert Wollny
  • 529
  • 2
  • 8