60

I was given the following as an interview question:

class A
{
public:
    void fun()
    {
        std::cout << "fun" << std::endl;
    }
};

A* a = NULL;
a->fun();

What will happen when this code is executed, and why?


See also:

Community
  • 1
  • 1
Rajendra Uppal
  • 19,218
  • 15
  • 59
  • 57
  • Looks like a null pointer exception waiting to happen to me. Why don't you compile, run, and see for yourself instead of asking here? – duffymo Mar 28 '10 at 15:48
  • 24
    Undefined behaviour. Or if the code is to be taken literally as a complete unit, a compilation error. –  Mar 28 '10 at 15:48
  • 7
    Tricky question, or trick question? It won't compile because `Class` (capital C) isn't a C++ keyword. – Ken Mar 28 '10 at 15:49
  • 1
    Please show the real question. Until then, i think we can't really answer seriously. – Johannes Schaub - litb Mar 28 '10 at 15:54
  • class keyword error and fun() private corrected. @ Johannes: This is the real question, it was asked as it is presented here. – Rajendra Uppal Mar 28 '10 at 15:56
  • 2
    @ duffymo, I have checked it and it prints "fun" and I couldn't figure out why, so I asked here. – Rajendra Uppal Mar 28 '10 at 16:00
  • 2
    Assuming that it compiles (i.e. that this is not meant to be the complete compilation unit), and that `NULL` has its usual definition, the answer "nasal demons" would probably get you bonus points for the interview :) http://catb.org/jargon/html/N/nasal-demons.html – Thomas Mar 28 '10 at 16:03
  • 16
    @Rajendra It doesn'nt matter what it does when you compile it with your specific compiler, the C++ Standard says that dereferencing a null pointer is undefined. So the next iteration of your compiler, or another compiler might do something different, but equally undefined. –  Mar 28 '10 at 16:03
  • 8
    How is this "tricky"? It's basic and, if you ask me, rather pointless. Creating a pointer, initializing it to NULL and using it in the very next line - how "typical"! – Daniel Daranas Mar 28 '10 at 16:08
  • 2
    Why was this closed and even worse, why is this being voted to delete? It is a valid question; it happens because of UB. Voting to reopen. – Amarghosh May 27 '10 at 08:15
  • 1
    @Amarghosh: because it was a lousy question. Fortunately, it is slowly improving... – Shog9 May 28 '10 at 17:00
  • @DanielDaranas that is not basic at all, this case of "using it" -as you put it-, is a pure vue d'esprit, a mere syntax construct to tell the compiler to resolve the type of a. The pointer is not followed so there is no "dereferencing null" here. (Since there is no dereferencing at all) Therefore, it is not UB. – v.oddou Dec 14 '17 at 05:56
  • Adding a 2nd comment here. The only way this could be seen as UB, is if we think of it like Java or C#. Where the instance actually matters to the abstract machine, since methods are fields (a la python). However this is not python, and C++ _can_ define the behavior of this case with a bit of discrimination: notably the case where there is no virtuality. – v.oddou Dec 14 '17 at 05:59
  • @v.oddou Please see [this answer](https://stackoverflow.com/a/2505559/96780) in a linked question. – Daniel Daranas Dec 14 '17 at 11:22
  • @v.oddou See also [this more thorough answer](https://stackoverflow.com/a/2474021/96780) to the question [When does invoking a member function on a null instance result in undefined behavior?](https://stackoverflow.com/q/2474018/96780). – Daniel Daranas Dec 14 '17 at 11:24

6 Answers6

70

It's undefined behavior, so anything might happen.

A possible result would be that it just prints "fun" since the method doesn't access any member variables of the object it is called on (the memory where the object supposedly lives doesn't need to be accessed, so access violations don't necessarily occur).

sth
  • 222,467
  • 53
  • 283
  • 367
  • Where is the address of the member function stored for a C++ class and how can it be accessed using the NULL pointer to the object of that class? – Kamal Mar 28 '10 at 16:08
  • 11
    @Kamal If the function is not virtual, then it gets statically linked. No need for a table. No need for the object pointer. – Frank Krueger Mar 28 '10 at 16:13
  • 4
    @Kamal The compiler could use static information (it knows the pointer is of type A) to find the function. The fact that the compiler can do this does mean that it must, and does not prevent this from being undefined behaviour. –  Mar 28 '10 at 16:13
  • 1
    @Kamal: Who said it must be stored? The compiler can transform the function call into `A::fun(a)`. – kennytm Mar 28 '10 at 16:14
  • 2
    @Kamal: The compiler knows the type of the object and the address of the method that should be called at compile time and can insert that address "hard coded". There is no need to look anything up at runtime. (This doesn't mean the compiler *has* to do it that way, but it could.) – sth Mar 28 '10 at 16:14
  • 1
    The object qualifies as POD, so I don't believe the compiler is allowed to have any hidden fields in the object to be used for finding member functions. That being the case, it would be very surprising if the compiler couldn't find the correct member function. It's not even allowed to have a lookup table mapping object pointers to member functions, due to the lifetime rules for POD types. There's very little flexibility in member function resolution here. Really, the fact that this is undefined behavior allows the compiler to inject an explicit null check to aid in debugging. – Ben Voigt Jul 02 '13 at 05:11
  • I want a proof with explicit standard quoting, that this is undefined behavior. In my book on the contrary, it's very provable (both statically and in the abstract machine) that the object and the method are callable from null since the function address is hard-replaced at compile time, and `this` is not dereferenced. Actually even `a` itself isn't dereferenced, it just looks like it, but it could be written as `decltype(a)::fun(a);` (after an imaginary step of build where implicit _this_ pointers are resolved to first parameters) – v.oddou Dec 14 '17 at 05:48
  • 1
    @v.oddou: See here for a discussion: https://stackoverflow.com/questions/2474018/when-does-invoking-a-member-function-on-a-null-instance-result-in-undefined-behav – sth Dec 15 '17 at 15:04
  • While it is true that it's undefined behaviour, and anything could happen, the fact is that functions don't exist within the class. In this situation, the functions are "bound" / associated to the outside class datatype. It's like an extension of the C structure, and this binding is done at the compilation phase, to the type; rather than at run time, in the instantiation phase. This is why I think you see so many compilers behaving in this way. Functions are not physically stored "inside" the class. – Owl Oct 25 '18 at 10:27
28

By the standard, this is undefined behavior and therefore a very bad thing. In reality of most programming platforms (across both X86 and several other architectures) this will run fine.

Why? Consider how class functions are implemented in C++. This isn't a virtual function, therefor this can be a static call to a known address. In x86 assembly, we can see this as

mov A, 0
mov ecx, A
call a__fun

since a__fun requires no instance data, even though it receives a null this pointer, nothing will happen.

Still shitty code and any compiler will scream, but it can run.

Daniel Goldberg
  • 19,908
  • 4
  • 21
  • 29
  • 3
    Yes, this is undefined behavior. Yes, this *may* run as expected on a given architecture. However it is wise to always keep the following wisdom in mind: "The worst possible outcome of undefined behavior is for it to do what you were expecting." – dgnuff Jun 26 '18 at 20:18
  • This answer ignores all "optimisations". If the compiler can see that the pointer is null it can just elide the call entirely. You're focused too much on the low level details of what happens to the call _if_ it happens. But there's a reason we call it undefined. That's not the same as "basically works". – Asteroids With Wings Apr 23 '20 at 13:59
20

The most likely behavior, on most modern computers, is that it will run, and print "fun", because:

  • C++ doesn't check whether the pointer is NULL before calling the function
  • fun() is not virtual, so there's no need to refer to a vtable to call fun()
  • fun() never access any member variables in A so it doesn't need to dereference the null this pointer.
lornova
  • 6,667
  • 9
  • 47
  • 74
Ken Bloom
  • 57,498
  • 14
  • 111
  • 168
11

We can't know what will. Everything can happen, because the program exposes undefined behavior. See Does invoking a member function on a null instance cause undefined behavior?.

Community
  • 1
  • 1
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
6

I have tried multiple times,all the time output is coming "fun" this is because function fun is independent of instance a. while calling a->fun(); a points to 0 so this is undefined behavior but in most of the compilers there should be no crash.

User97693321
  • 3,336
  • 7
  • 45
  • 69
5

Three points might help:

1) All Functions are stored in code or text section.

2) Non Virtual functions are resolved at complie time.

3) While calling to member functions of class, we pass current object as this pointer to that function.

Coming to your question , here fun() function is already in memory(code section / text section). As function fun() is non virtual , it will be resolved at complie time (i.e, for this line it will jump to instruction X at code section with this pointer as NULL). As no member variable and no virtual function are used/called in fun() function, it is working fine.