Calling Class Method Through Null Class Pointer

Calling class method through NULL class pointer

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

Pointer this of a class turns into null when calling a method of that class C++

The assumption: "textures is not null pointer because i can access to "applyTexture" from there." is wrong. applyTexture is not a function pointer, it's a class method.

The compiler actually converts your object notation call into:

PAGTexture::applyTexture(textures, t + i, id_revol.at(i));

passing nullptr doesn't bother the compiler like at all. But when entering the method, this==nullptr and it crashes when you access a member.

It's different with data members (would probably have crashed at once), hence your confusion.

To play it safe, you could do things like:

void PAGTexture::loadTexture(char * path_img, GLuint min_filter, GLuint mag_filter)
{
assert(this!=nullptr);

that will crash with a failed assertion if method is called with a null pointer (note: only works if optimizations are turned off, else the compiler assumes that this cannot be nullptr when optimizing even with -O1)

Why does calling method through null pointer work in C++?

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.

Method in null class pointer (c++)

Why not simply a namespace-scope function like this?

bool isValid(Foo* f) {return f && f->isValid();}

An if-Statement like

if (aFoo->isValid())

Implies that the pointer is pointing to a valid object. It would be a huge source of confusion and very error prone.

Finally, your code would indeed invoke undefined behavior - aFoo->isValid is per definition equivalent to (*aFoo).isValid:

N3337, §5.2.5/2

The expression E1->E2 is converted to the equivalent form
(*(E1)).E2;

which would dereference a null pointer to obtain a null reference, which is clearly undefined:

N3337, §8.3.2/5

[ Note: in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the
“object” obtained by dereferencing a null pointer, which causes
undefined behavior. […] — end note ]

Accessing members of class using nullptr in C++

According to my knowledge, we can access the members of the class through pointers by making pointer to the class and then store the address of an object of that class type, and then we can access the members through '->' using that pointer

That is correct. Though, unless you need to, you would not use a pointer, but just the object itself:

Check ptr;
ptr.print();

How and why is it working without any error ...

You do not get an error, because dereferencing a null pointer is undefined behavior. Compilers may emit a warning in cases they can detect the problem, but they are not required to issue an error (and in general they cannot).

... or undefined behaviour even though i did not store an address of object in it

You code does have undefined behavior. Undefined behavior means that you get no guarantee that your code will do the right thing. You do not get a guarantee that your code will do something wrong.

Behind the scenes the this pointer is passed as implicit parameter to member functions. As print is not actually using any members of the class, the pointer isn't used and your code appears to work. However, this is just by chance. By the rules of the language ptr->print(); is already undefined behavior (no matter if print does use members or not).

Accessing class members on a NULL pointer

The object foo is a local variable with type Foo*. That variable likely gets allocated on the stack for the main function, just like any other local variable. But the value stored in foo is a null pointer. It doesn't point anywhere. There is no instance of type Foo represented anywhere.

To call a virtual function, the caller needs to know which object the function is being called on. That's because the object itself is what tells which function should really be called. (That's frequently implemented by giving the object a pointer to a vtable, a list of function-pointers, and the caller just knows it's supposed to call the first function on the list, without knowing in advance where that pointer points.)

But to call a non-virtual function, the caller doesn't need to know all that. The compiler knows exactly which function will get called, so it can generate a CALL machine-code instruction to go directly to the desired function. It simply passes a pointer to the object the function was called on as a hidden parameter to the function. In other words, the compiler translates your function call into this:

void Foo_say_hi(Foo* this);

Foo_say_hi(foo);

Now, since the implementation of that function never makes reference to any members of the object pointed to by its this argument, you effectively dodge the bullet of dereferencing a null pointer because you never dereference one.

Formally, calling any function — even a non-virtual one — on a null pointer is undefined behavior. One of the allowed results of undefined behavior is that your code appears to run exactly as you intended. You shouldn't rely on that, although you will sometimes find libraries from your compiler vendor that do rely on that. But the compiler vendor has the advantage of being able to add further definition to what would otherwise be undefined behavior. Don't do it yourself.

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

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



Related Topics



Leave a reply



Submit