Sign in to follow this  

NULL exception help

This topic is 4590 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hiya! I've been getting this NULL pointer exception in the 2nd run-through of my game loop, the project is here. It's a strange one, so I'd be very happy if anyone can help me. Please don't yell at me about such things as my ofstream error logs because error logging is not my main focus at the moment, although it should be indeed. Anyways, I store my sprites for each character(Entity) in an array linkedlist. So I have a list for the breathing animations at the moment, but each set of animations will have their own index in the array once I can figure this issue out. So when I run through the gameloop, the 2nd run-through in the debugger tells me that my player Entity's currentImage is now non-existant. I can NOT figure out why.

Share this post


Link to post
Share on other sites
1)Always check your pointers before using them.
//example:
if(pPointer != NULL)
{
pPointer->UseMe();
}
else
{
OutputDebugString(TEXT("Encountered pPointer is NULL!\r\n");
}

2) Check every usage of the pointer that becomes NULL.

Can you point us the exact codefragment when the exception occurs?
(So we can see how safe it is programmed)

greetz,

Ward

Share this post


Link to post
Share on other sites
Quote:

if(pPointer != NULL)
{
pPointer->UseMe();
}
else
{
OutputDebugString(TEXT("Encountered pPointer is NULL!\r\n");
}

That's expensive! By all means test them, or atleast at the begining of each function or something, but don't test for null on a pointer which you "know" can't be, assert instead (as the first answer said). This way there is no runtime overhead in release builds.


#include <assert.h>

assert(pPointer);
pPointer->UseMe();


And yeah, use the debugger. The debugger will be quicker in the short term. The asserts will save you time in the long run.

Share this post


Link to post
Share on other sites
Checking every pointer before using them seems to be a bit of overkill, because you do get an exception, which breaks into the debugger. Then just use your debugger to check which variable that was NULL.

Some general comments on your program: Why do you compile it with .NET Managed Excetions, when you use only plain C++? Is this just an oversight? You can change the setting in Project Options -> General -> Use Managed Extensions.

Why do you implement your own linked list, when STL has a implementation in std::list. That would have avoided this bug....

You are welcome to ask again if you do not find the pointer with the wrong value.

Share this post


Link to post
Share on other sites
Quote:
Original post by Squirm
That's expensive! By all means test them, or atleast at the begining of each function or something, but don't test for null on a pointer which you "know" can't be, assert instead (as the first answer said). This way there is no runtime overhead in release builds.


I've had some experiences before that some variables where not properly initialized. In debugmode they are mostly initialized to zeroes, but in releasemode then where initialized to mostly a random value (all depending on the platform).
Because it is possible the originator of the problem of 'this thread' has made an initialisation error, this will still result in a crash free program.

Of course another tip will be checking all initialisations of all variables and set them properly.

Share this post


Link to post
Share on other sites
Hello ppl, thanks for the criticism and tips. I used my own LinkedList because... just because it was an added challenge and I wanted to see if I could sort this problem out now that I have it.
I HAVE used the debugger a ton of times before posting this. I have tried and tried but I can NOT determine where the pointer becomes NULL. The first run through the game loop the characterList's values are fine. The images show as they should, but the 2nd run through the loop (I swear I do not change anything with the Entity or call GetNext() on the LinkedList), the characterList suddenly has NULL pointers to the current spot, next, and previous spot as well. So when I call
characterList[currentPlace].GetCurrent();
I get the NULL pointer.

I guess I should look into using STL's list.
Quote:
Some general comments on your program: Why do you compile it with .NET Managed Excetions, when you use only plain C++? Is this just an oversight? You can change the setting in Project Options -> General -> Use Managed Extensions.
What exactly ARE managed extensions?

Share this post


Link to post
Share on other sites
Have you considered the problem of a stack overwrite?
Perhaps do an array bounds checking (by doing code review).
An overwrite of 1 byte is enought to mess up the stack and give unwanted results.

Again, can you give us a downscaled example of your code that gives the exception?

Share this post


Link to post
Share on other sites
I've done a quick code review (debugging) and
after changing the line:

void Video::Render(HDC &hDC, Entity ent1, Entity ent2)

to

void Video::Render(HDC &hDC, Entity *ent1, Entity *ent2)

You must also then replace ever ent1.function() by a
ent1->function(), for both ent1 and ent2 in the Render procedure.
And call the Render procedure from the main loop like this:
Render(hDC, player1, player2); (the * signs must be removed)

I can get the program run. I don't know what you expect from the output, but at least it does not crash.

What you were doing there was passing physical copies of and instance of Entity-class. The Render procedure on his turn calls methods that changed several membervariables of those copies. The changings are persistent on the dynamic memory variables, but not on the stack memory variables (because these are copies).
This, according to me, can result in strange behaviour (and possibly a crash).

Hope you understand this bugfix.

greetz,

Ward







Share this post


Link to post
Share on other sites
OK, I will give you some quick tips before I have to get to the next meeting, will give you more details later tonight.

It is nice to hear that you wanted to get some extra challenge by implementing a linked list. I guess you got your extra challenge now :-D

It is not completely correct that the pointers are NULL. When I run it I get them to be 0xFEEEFEEE, which is the fill pattern Visual Studio uses to fill deleted memory. This gives a strong indication that you delete the memory and then try to use it.

I ran the program and placed a breakpoint that stopped the debugger when the memory that characterList pointed to changed. When I saw where the memory was deleted, the solution was easy.

WardVT's solution works, because before you copied the players in the call to Render(). That will copy all the members of player1. Because characterList is a pointer, only the pointer will be copied, not what it points to. Therefore you have two objects: ent1 and (*player1), which both points to the same characterList. When Render returns, ent1 will be deleted and in its destructor will delete the characterList. This will cause player1->characterList to point to deleted memory.

There are two solutions to this:
1. Implement the copy-constructor Entity(const Entity& entity) and operator=(const Entity& entity) on Entity. Both these should be implemented to copy the not only the pointer, but the whole linked list (this means that you probably will have to implement those two methods on the linked list too).
2. Make it impossible to copy the object: this should be done for all objects where you do not implement copy-constructor and operator=. You do it by declaring those methods private and NOT implementing them.

Another tip can be to turn up your warning level to level 4 to get some more hints of where your code could have problems.

Hope you will solve the bug now.
[Edit spelling]

[Edited by - EliasAE on May 18, 2005 12:47:49 PM]

Share this post


Link to post
Share on other sites
Implementing that copy constructor (see EliasAE) will indeed work, BUT it would decrease the performance too much.

btw, I'm very curious to see the final result of this small game.

greetz,

Ward

Share this post


Link to post
Share on other sites
Making it impossible to copy the thing is good, however. First, because a default copy contructor is created for you if you don't and it is clearly invalid, and secondly because it would immediately fail at compile time when you accidently copied it anyway.

Share this post


Link to post
Share on other sites
Thanks everyone!! Yesterday I was able to figure out the solution that WardTV pointed out (on my own, which is always good). I now Entity->Iterate() before I call Video->Render(). Of course, I kicked myself in the arse for being SOO completely oblivious to this because I passed the Entity in as a non-pointer so I could not change anything in Render(). haha
Good times.

Thanks also to EliasAE, who pointed out some very useful things I can keep in mind for the future, such as the memory fill pattern!

Share this post


Link to post
Share on other sites

This topic is 4590 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this