21

Possible Duplicate:
Calling class method through NULL class pointer

#include <iostream>
using namespace std;
class test
{
    int i;
public:
    test():i(0){ cout << "ctor called" << endl;}
    void show()
    {
        cout<<"show fun called"<<endl;
    }
};

int main(int argc , char *argv[])
{
    test *ptr = NULL;
    ptr->show();
    return 0;
}

clearly, no ctor will be called. Is this standard? or just some compiler optimization as this pointer is not used in show() member function?

Community
  • 1
  • 1
bbc
  • 1,061
  • 4
  • 13
  • 21
  • 7
    Dereferencing a null pointer is UB. – chris Jul 04 '12 at 00:05
  • 2
    Add `i = 1;` inside `show()` and try to run it. – Jesse Good Jul 04 '12 at 00:14
  • 1
    chris, UB means up to compiler implementation? and I am using g++ 4.6.3. Jesse Good, of course, seg fault, there is no doubt. I am wondering if compiler will generate code without this for member function which does not need it. – bbc Jul 04 '12 at 00:22
  • 1
    @bbc: UB means "undefined behavior", which is different than "implementation defined". Implementation defined means that the behavior is at least defined, though that definition may vary between compilers. Also; *"of course, seg fault, there is no doubt."* - Actually, there is a ton of doubt, because the behavior is *undefined*. If it were sure to cause a segfault then it would be perfectly well defined, which it is not. Anything can happen, though in practice a segfault is likely (you hope). – Ed S. Jul 04 '12 at 00:46
  • Your code is valid under most compilers [No crashing on GCC and MSVC here]. Luckily, your show() method qualifies as pure STATIC. you are not DEREFERENCING the pointer! Function Call on Pointer to non-polymorphic class does NOT dereference the pointer. It merely CALLs the Address of the method with stack frame in which this pointer is zeroed. If your code then only uses global variables and never touches `this` pointer - or the non-static data members - you are okay. Touching the static data members is also okay. Better, just mark your method static and forget about the pointer! – Петър Петров Oct 08 '14 at 01:23

4 Answers4

41

The pointer isn't needed to call the method. The type of the pointer is known, so the code for the method is known. The method doesn't use this, so it runs the code just fine. It's undefined behavior, but its more efficient not to check if the pointer is NULL, so it runs.

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
  • 2
    (How) would a virtual method affect his observed behavior? –  Jul 04 '12 at 00:16
  • 3
    I would expect a virtual method call to fail, since it needs to look up the method in the vtable, which it would find at the other end of the pointer, but the pointer is NULL. – Ned Batchelder Jul 04 '12 at 00:29
  • 1
    seg fault for virtual with g++, not sure this is also implementation dependent. will compiler generate vptr and vtblr without object of class? guess not for efficiency reason? – bbc Jul 04 '12 at 00:35
  • 1
    Classic non-virtual methods are called directly with asm call. The stack frame then has `this` pointer zeroed. Virtual methods however will most-likely segfault because the pointer must be dereferenced. – Петър Петров Oct 08 '14 at 01:27
11

If you look at the assembly (for at least one compiler), you can see why it runs (even though it is undefined behavior as many have pointed out). For these two lines:

test *ptr = NULL;
ptr->show();

This assembly is generated (in one compiler I just tried):

00000004: C7 45 FC 00 00 00  mov         dword ptr [ebp-4],0
          00
0000000B: 8B 4D FC           mov         ecx,dword ptr [ebp-4]
0000000E: E8 00 00 00 00     call        ?show@test@@QAEXXZ

It pushes the NULL (0) on the stack and calls the method since the address of the method is independent of the actual object instance.

Mark Wilkins
  • 40,729
  • 5
  • 57
  • 110
3

It is not valid, the behavior is undefined and actual results depended on your compiler.

Soren
  • 14,402
  • 4
  • 41
  • 67
  • 1
    Well, it's valid. __thiscall function that does not access `this` pointer is just a static function. Just add "static" - it is the best you can do in code that is static by definition :) And it forces the function to use __cdecl, so no this pointer requirement. Note that adding virtual will then make more complicated preparation that requires dereferencing the pointer, and will then segfault. – Петър Петров Oct 08 '14 at 01:38
1

Well, first off, it's not valid as it invokes undefined behavior. You are really asking why the compiler allows it, and the answer is because that is boneheaded code that simply won't occur in a real application, so why bother? The real problem comes when the pointer is made invalid at runtime in a way that cannot be anticipated by static code analysis.

The compiler is not there to hold your hand, it is there to compile your code according to the standard. If it offers useful warnings then great, but there is nothing syntactically or semantically illegal there, you are simply writing code which causes undefined behavior.

Ed S.
  • 122,712
  • 22
  • 185
  • 265