C++ "this" pointer?

Started by
35 comments, last by pdugan 21 years, 11 months ago
In the process of writing a Texture manager class, I came across a peculiar bug: a this pointer that is NULL. I was wondering if anyone else has come across this, and knows under what circumstances a this pointer can be null. Also, as a bonus question to any more experienced programmers: When dealing with pointers/references passed between functions, where does the responsibility of testing the pointers for validity lie? Should the calling function test a pointer it is going to pass for NULL? Should the recieving function perform this chore? Or should this test (and/or assert()) be done in both? Thanks in advance, Patrick "a riddle wrapped in a mystery inside an enigma" - Churchill
"a riddle wrapped in a mystery inside an enigma" - Churchill
Advertisement
quote:Original post by pdugan
In the process of writing a Texture manager class, I came across a peculiar bug: a this pointer that is NULL. I was wondering if anyone else has come across this, and knows under what circumstances a this pointer can be null.

It is my understanding that the "this" pointer refers to the active object's scope. If the active object has not been "newed" then "this" may be null. But don't take my word on that.
quote:
Also, as a bonus question to any more experienced programmers: When dealing with pointers/references passed between functions, where does the responsibility of testing the pointers for validity lie? Should the calling function test a pointer it is going to pass for NULL? Should the recieving function perform this chore? Or should this test (and/or assert()) be done in both?

In practice, I have seen that the receiving function is responsible for validating parameters. I am not quite sure the reasoning behind it, but it seems to be an accepted practice.



-----------------------------
kevin@mayday-anime.com
http://games.mayday-anime.com

-- edit: spelling

[edited by - grasshopa55 on May 2, 2002 4:51:10 PM]
-----------------------------kevin@mayday-anime.comhttp://www.mayday-anime.com
if this is NULL then the object has not been created properly.

now, about validating parameters.... it''s really a performance/stability issue. if you have a small function that going to be called thousands of times in your render loop. (for example, let''s say glVertex4fv ). there is no way you want glVertex4fv constantly calling IsBadReadPtr to validate the pointer, in your render loop. so glVertex4fv would be documented that it expects as a precondition that the pointer passed to it, be a valid readable pointer of 16 bytes (4 floats) in size. the opposite holds in reverse, i.e. a function like GetDC probably checks that the handle passed to it, is a valid window handle, because it''s not a time critical function.

To the vast majority of mankind, nothing is more agreeable than to escape the need for mental exertion... To most people, nothing is more troublesome than the effort of thinking.
To the vast majority of mankind, nothing is more agreeable than to escape the need for mental exertion... To most people, nothing is more troublesome than the effort of thinking.
quote:Original post by pdugan
In the process of writing a Texture manager class, I came across a peculiar bug: a this pointer that is NULL. I was wondering if anyone else has come across this, and knows under what circumstances a this pointer can be null.

this can never be NULL under any legal circumstances. An example of undefined behaviour under MSVC++6 which produces this effect is as follows:

    #include <iostream>using namespace std;struct A{	void f()	{		if(this)			cout << "OK" << endl;	}};int main(){	A *pa = 0;	pa->f();}    


Despite the fact that this appears to work under MS, do not be fooled. It is strictly *undefined behaviour*, yet I've seen programmers do this in production code, and I believe there are instances of this code in MFC. It is illegal to dereference a NULL pointer, which is what operator-> does.
quote:
Also, as a bonus question to any more experienced programmers:

Oh, it's a quiz now, is it?
quote:
When dealing with pointers/references passed between functions, where does the responsibility of testing the pointers for validity lie?

A reference *must* be bound to an object, so it is again illegal to have a situation which results in anything other than that. That said, it should be apparent that you prefer references to pointers when there has to be a referent. So, you should be left with the situation where it is semantically valid to pass a NULL pointer into a function, leaving the responsibility for checking the pointer firmly with the function. There are exceptions, so use this is a rule of thumb.

[ C++ FAQ Lite | ACCU | Boost | Python | Agile Manifesto! ]

[edited by - SabreMan on May 2, 2002 5:46:42 PM]
one possible cause of a NULL this pointer is an invalid type cast of a pointer. the member function you are calling doesn''t exist on the class you cast but because of your typecast the compiler allows it without errors.
Another time you will see a null ''this'' pointer is when two threads are accessing an object and the object gets deleted by one of them. If one thread deletes the object while the second thread is executing in a member function, the object will no longer exist and the ''this'' pointer will be invalid; sometimes it will be NULL and other times it will be a wild pointer.


Dire Wolf
www.digitalfiends.com
[email=direwolf@digitalfiends.com]Dire Wolf[/email]
www.digitalfiends.com
Wow, thank you everyone for the prompt reply; I was not expecting such punctual assistance.

Sabreman, your code sample was spot on. This is precisely the behaviour I am experiencing: ''if (this)'' will let the program run successfully, but ''assert (this)'' throws an error.

I''m currently looking into changing how my TextureManager class (and other classes) are instantiated (ie: not using direct pointers and ''new'').

The object arrangement I have currently is an Engine class using the facade design pattern (see Design Patterns, GOF). A LoadPlugins(...) method new''s the Engine''s pointers corresponding to the correct plugins. Now, if I was loading the plugins using the Engine class''s constructor, I would simply represent the plugin objects as references and be done with it. However, I would like to defer loading of the plugins as the Engine constructor requires some setup parameters (and I''d like to break the interface down to be as simple as possible). I also don''t want to statically declare the plugins in the Engine class, as I want the user to be able to load only the features they need to reduce the memory/processing footprint.

Btw, if there''s any interest in looking at my code, I''d be happy to put it on my website, and/or setup a CVS server.

Thanks again for all your help, and I hope I''m not pushing my luck with another question.

"a riddle wrapped in a mystery inside an enigma" - Churchill
"a riddle wrapped in a mystery inside an enigma" - Churchill
The major recommendation I''d make for pointer management is to familiarise yourself with various smart pointers. Check out the Boost website (see my sig) where you can freely download their libraries. There''s a *lot* of really useful stuff, and their shared_ptr is a glaring omission from the Standard Library.

I hope I got my message across about the NULL "this" pointer. In my code, where I am saying if(this), that in itself is OK. What''s not OK is that you would even get as far as calling the function with a NULL this pointer, since it''s illegal to dereference a NULL pointer. Therefore, the if(this) check is futile, because the code has already invoked undefined behaviour and you cannot rely on anything. You might get seemingly reasonable results on MS''s compiler, but the C++ Standard makes no guarantees, and I''m not sure even MS''s compiler behaves in the same way when multiple inheritance is involved.

[ C++ FAQ Lite | ACCU | Boost | Python | Agile Manifesto! ]
since it is possible to call methods of a class - class::method() - without refering to an instance of the class, then it''s very possible to have a null ''this''.

one implementation of the singleton pattern makes use of calling a function on a non existant object - Singleton::Instance()

if all your functions are non pure, all data static then you don''t really need an instance of the class. it''s pretty unusual though and best avoided - unless it''s a well documented and understood use.

actually, i guess a texture manager class would be a prime candidate for the singleton pattern, so maybe that''s what you are witnessing.
quote:Original post by petewood
since it is possible to call methods of a class - class::method() - without refering to an instance of the class, then it's very possible to have a null 'this'.

Not without invoking illegal (undefined) behaviour. There are *no* exceptions.
quote:
one implementation of the singleton pattern makes use of calling a function on a non existant object - Singleton::Instance()

That would require Instance() to be a static member function. Static members do not have a 'this' pointer.
quote:
if all your functions are non pure, all data static then you don't really need an instance of the class. it's pretty unusual though and best avoided - unless it's a well documented and understood use.

It's completely illegal!

[ C++ FAQ Lite | ACCU | Boost | Python | Agile Manifesto! ]

[edited by - SabreMan on May 4, 2002 8:08:56 AM]

This topic is closed to new replies.

Advertisement