2

I have a core file where the application crashed inside a method which was called on a NULL-pointer:

class myclass{
    myclass_impl* impl;

    void func();
}

func(){impl->implFunc();}

The application crashes since the member impl is NULL. But the stracktrace ends in myclass_impl::implFunc() with *this beeing NULL.

How is that even possible?

Beginner
  • 5,277
  • 6
  • 34
  • 71
  • 1
    **This is not a duplicate**. The linked question asks what happens when you call a method on a null reference. This question knows (it crashes), but asks why a callstack behaves the way it does. – Qix - MONICA WAS MISTREATED Nov 10 '15 at 09:49
  • @Qix the top answer of the duplicate also answers this question. It's possible because the behaviour is undefined and therefore anything may happen. *Anyhing* includes pointers being null. – eerorika Nov 10 '15 at 09:54
  • I'm not sure I understand this question. If it's clear that the application crashes, then it's also clear the application is likely to crash somewhere related to the problem at hand. – MSalters Nov 10 '15 at 09:57
  • 1
    @MSalters question is asking how the stacktrace knows what method was called when it crashed if the `this` pointer was `NULL`. – Qix - MONICA WAS MISTREATED Nov 10 '15 at 09:58
  • 1
    @Qix: I'm not sure I agree with your interpretatin of the question. Besides, a stack trace is an approximation anyway. It assumes that a function call is instant: either `foo()` is on the call stack or it isn't. In reality, it takes multiple instructions to make a function call, and any of these can cause a segfault. Should `foo()` be shown on the callstack then? Matter of opinion, but in general it doesn't hurt. – MSalters Nov 10 '15 at 10:03
  • @msalters I find the answer qix gave helpful. how can the instructions during a function call lead to a crash? I would like to get a technical understanding beyond the fact that the standard says it isn't defined. – Beginner Nov 10 '15 at 11:09

1 Answers1

4

Because the location of the function implFunc() is known. It has an address, therefore we know that we're inside it when we look at the call stack.

However, the this pointer that was used to call that function is set to 0 (or really, some undefined, but unallocated, value - depending on how it's used).


You can think of member methods like functions that take an implicit first argument as the this value (in fact, that's exactly what happens on many platforms). You don't need pointers to be valid in order to call a function. The call will at least reach the function, and thus place the function's location on the call stack (which is what is used to generate a backtrace), and what happens inside the function is up to whether or not you dereference that pointer.

Your scenario, then, means you called that function with the implicit first parameter being a NULL pointer. The function call itself succeeded, but the pointer being used inside the function (method) failed because you dereferenced a null pointer.

Community
  • 1
  • 1
Qix - MONICA WAS MISTREATED
  • 14,451
  • 16
  • 82
  • 145