What Will Happen When I Call a Member Function on a Null Object Pointer

What will happen when I call a member function on a NULL object pointer? [duplicate]

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).

Is it legal to call a non-static member function of a stateless class on a nullptr? [duplicate]

Even though the struct is empty, it has a non zero size. There must be some memory that act as a storage for it.

No. This is always UB. Make it static if you don't need the instance. Static functions are still callable using the dot . syntax.

Why? Because you cannot dereference a null pointer. Calling a member function equivalent to this:

 EmptyStruct *esptr = nullptr;
(*esptr).nonstatic_mf();

As you can see, the null pointer is deferenced, which is UB.

What does the standard says about this? From [class.mfct.non-static]/2:

If a non-static member function of a class X is called for an object that is not of type X, or of a type derived from X, the behavior is undefined.

A null pointer don't point to a valid instance of EmptyStruct. This alone is enough to make the behaviour undefined

And from [expr.ref]/2:

For the first option (dot) the first expression shall be a glvalue.
For the second option (arrow) the first expression shall be a prvalue having pointer type.
The expression E1->E2 is converted to the equivalent form (*(E1)).E2; the remainder of [expr.ref] will address only the first option (dot).

So esptr->nonstatic_mf() is effectively equivalent to (*esptr).nonstatic_mf(), and derefencing a null pointer is undefined behaviour.

So there's two way in which this code is undefined.

Calling class method through NULL class pointer [duplicate]

Under the hood most compilers will transform your class to something like this:

struct _ABC_data{  
int a ;
};
// table of member functions
void _ABC_print( _ABC_data* this );

where _ABC_data is a C-style struct
and your call ptr->print(); will be transformed to:

_ABC_print(nullptr)

which is alright while execution since you do not use this arg.


UPDATE: (Thanks to Windows programmer for right comment)

Such code is alright only for CPU which executes it.

There is absolutely positively no sane reason to exploit this implementation feature. Because:

  1. Standard states it yields undefined behavior
  2. If you actually need ability to call member function without instance, using static keyword gives you that with all the portability and compile-time checks

Calling member function via pointer C++, object is null?

The reason of the problem is the following.

You declared a node using the default constructor.

ListNode sum;

It seems that the default constructor sets the data member next to nullptr and the data member val to the value INT_MIN (that does not make a sense).

Then you are calling the member function append the first time using the pointer sum_ptr.

ListNode* sum_ptr = ∑
//...
sum_ptr->append(temp_sum);

The member function append in this case just changes the data member val.

void ListNode::append(int v){
if(this->val == INT_MIN){
this->val = v;
}
//...

And then you are reassigning the pointer in the while loop

sum_ptr = sum_ptr->next;

So now the pointer sum_ptr has the value of the data member sum.next that is equal to nullptr. And you are using this null pointer in a next call of the member function append that results in undefined behavior.

Also pay attention to that for example this pair of statements

temp_sum = temp_sum >= 10 ? temp_sum - 10 : temp_sum;
c_over = temp_sum >= 10 ? 1 : 0;

does not make a sense because after execution of the first statement temp_sum is always less than 10. So the variable c_over always will be set to 0. You need at least to exchange these statements.

Why doesn't the program crash when I call a member function through a null pointer in C++?

You're not using any member variables of A - the function is completely independent of the A instance, and therefore the generated code happens to not contain anything that dereferences 0. This is still undefined behavior - it just may happen to work on some compilers. Undefined behavior means "anything can happen" - including that the program happens to work as the programmer expected.

If you e.g. make mprint virtual you may get a crash - or you may not get one if the compiler sees that it doesn't really need a vtable.

If you add a member variable to A and print this, you will get a crash.

Pointer still able to call member function, after it was set to NULL and delete being called on it [duplicate]

If a program accesses an object outside of its lifetime, then the behaviour of the program is undefined. Your program accesses an object outside of its lifetime. The behaviour of your program is undefined. The behaviour that you observed is because the behaviour is undefined. You could have observed any other behaviour because it is undefined, but you didn't observe other behaviour because it's undefined.

When does invoking a member function on a null instance result in undefined behavior?

Both (a) and (b) result in undefined behavior. It's always undefined behavior to call a member function through a null pointer. If the function is static, it's technically undefined as well, but there's some dispute.


The first thing to understand is why it's undefined behavior to dereference a null pointer. In C++03, there's actually a bit of ambiguity here.

Although "dereferencing a null pointer results in undefined behavior" is mentioned in notes in both §1.9/4 and §8.3.2/4, it's never explicitly stated. (Notes are non-normative.)

However, one can try to deduced it from §3.10/2:

An lvalue refers to an object or function.

When dereferencing, the result is an lvalue. A null pointer does not refer to an object, therefore when we use the lvalue we have undefined behavior. The problem is that the previous sentence is never stated, so what does it mean to "use" the lvalue? Just even generate it at all, or to use it in the more formal sense of perform lvalue-to-rvalue conversion?

Regardless, it definitely cannot be converted to an rvalue (§4.1/1):

If the object to which the lvalue refers is not an object of type T and is not an object of a type derived from T, or if the object is uninitialized, a program that necessitates this conversion has undefined behavior.

Here it's definitely undefined behavior.

The ambiguity comes from whether or not it's undefined behavior to deference but not use the value from an invalid pointer (that is, get an lvalue but not convert it to an rvalue). If not, then int *i = 0; *i; &(*i); is well-defined. This is an active issue.

So we have a strict "dereference a null pointer, get undefined behavior" view and a weak "use a dereferenced null pointer, get undefined behavior" view.

Now we consider the question.


Yes, (a) results in undefined behavior. In fact, if this is null then regardless of the contents of the function the result is undefined.

This follows from §5.2.5/3:

If E1 has the type “pointer to class X,” then the expression E1->E2 is converted to the equivalent form (*(E1)).E2;

*(E1) will result in undefined behavior with a strict interpretation, and .E2 converts it to an rvalue, making it undefined behavior for the weak interpretation.

It also follows that it's undefined behavior directly from (§9.3.1/1):

If a nonstatic member function of a class X is called for an object that is not of type X, or of a type derived from X, the behavior is undefined.


With static functions, the strict versus weak interpretation makes the difference. Strictly speaking, it is undefined:

A static member may be referred to using the class member access syntax, in which case the object-expression is evaluated.

That is, it's evaluated just as if it were non-static and we once again dereference a null pointer with (*(E1)).E2.

However, because E1 is not used in a static member-function call, if we use the weak interpretation the call is well-defined. *(E1) results in an lvalue, the static function is resolved, *(E1) is discarded, and the function is called. There is no lvalue-to-rvalue conversion, so there's no undefined behavior.

In C++0x, as of n3126, the ambiguity remains. For now, be safe: use the strict interpretation.

c++: why can't 'this' be a nullptr?

Question 1: does the C++ standard (any flavor) disallow a NULL this?
Or is g++ just getting in my face?

The C++ standard disallows it -- calling a method on a NULL pointer is officially 'undefined behavior' and you must avoid doing it or you will get bit. In particular, optimizers will assume that the this-pointer is non-NULL when making optimizations, leading to strange/unexpected behaviors at runtime (I know this from experience :))

Question 2. More philosophically, why? 'this' is just another pointer.
The glory of pointers is that they can be nullptr, and that's a useful
condition.

I'm not sure it matters, really; it's what is specified in the C++ standard, and they probably had their reasons (philosophical or otherwise), but since the standard specifies it, the compilers expect it, therefore as programmers we have to abide by it, or face undefined behavior. (One can imagine an alternate universe where NULL this-pointers are allowed, but we don't live there)



Related Topics



Leave a reply



Submit