views:

4223

answers:

9

I have a Linux C++ application and I'd like to test an object pointer for validity before dereferencing it. However try/catch doesn't work for this on Linux because of the segmentation fault. How can this be done?

+4  A: 

Initialize your pointer to NULL. If after some processing it is still NULL it’s invalid, otherwise it’s valid.

Bombe
If I delete an object it's pointer is not NULL but points to invalid memory. How can I validate such pointer?
Jack
Why the hell would you even want to? You deleted it. If you are using pointers anywhere and you’re not sure whether they’re deleted or not you are doing something VERY wrong.
Bombe
I second that. Invalid pointers are invalid pointers. Either afterwards the pointer-variable is not accessible anymore, or you set it to 0. Or, as this is C++, learn about RAII.
gimpf
+3  A: 

You could enable a signal handler for SIGSEGV for this one occurrence. See the man page "signal" for details. The other alternative is to use references which are guaranteed to be valid. It depends on your application of course.

Greg Reynolds
The man page says a the process state is undefined if it ignores the SIGSEGV. Can I resume C++ application after catching SIGSEGV?
Jack
Good question - probably not safely. I think it is generally better to use references instead of pointers if you are worried about validity. As the other posters have pointed out you can log where the error happens and correct it.
Greg Reynolds
References are also not guaranteed to be valid. If the lifetime of the object referenced ends before the reference is used, the results are also undefined (in practice identical to an invalid pointer). References cannot be initialized to null, and not reset. That's it.
gimpf
True - but if you are using them "normally" then they are less likely to give you a problem. I should have been a bit clearer in that you can set a pointer to any old rubbish, but a reference (at least at first) is a lot more difficult to get wrong. I blame my nasty cold for slow wits :-(.
Greg Reynolds
+4  A: 

A segmentation fault is not an Exception (like Java's NullPointerException); it is a signal sent from the OS to the process. Have a look at the manpage for sigaction for pointers on how to install a handler for the segmentation fault (SIGSEGV).

João da Silva
+1  A: 

How do you test the pointer for validity? Compare to NULL?

The best thing you do is to run your program under Valgrind. A bug might be in a quite different place.

Update: On Win32 platform there is something like __try __except which allows to catch some exceptions. As far I know there is no Linux equivalent for that Win32 feature.

Greg Dan
On Windows you can catch an exception when accessing a pointer to deallocated object and you can deal with the situation. On Linux you get SIGSEGV. My question is there any way to validate a pointer that once pointed to a an object and hence is not NULL but still invalidated by delete operator.
Jack
I am not Win32 expert but once I used __try __except for such things.
Greg Dan
Those are windows-only things, exposing the platform's "Structured exception handling" (SEH) in C++. The linux equivalent is signals... but I think Shmoopty's suggestion of shared_ptr/weak_ptr is more along the right lines.
timday
A: 

If you attach a handler to the SIGSEGV there isn't much you can do besides log the fact that the error occurred and fail gracefully. Your program is in an undefined state when this violation occurs and it therefore may not be safe to continue normal operation.

Beyond checking for NULL I don't believe there is a way to check if a pointer is 'valid' in the sense you are describing. During normal operation errors like this shouldn't happen as they represent a bug, so you should want your program to fail, albeit gracefully.

mabbit
A: 

Pointers are stored in objects. They are initialized in the constructor, potentially to 0 (NULL). They're deleted in the destructor, possibly in assignment and rarely in other functions. When deleted in members other than the destructor, they're immediately assigned a new value or 0.

MSalters
+2  A: 

There is no natural, universal way with raw C++ pointers. C++ assumes that you will track that information.

In most situations, you can handle this by remembering to set pointers to NULL when they are invalid. New pointers that initially don't point should be set to NULL and newly deleted objects should have their pointers set to NULL.

Shmoopty
+5  A: 

If you have a scenario where many pointers across your app reference the same limited-lifetime objects, a popular solution is to use boost smart pointers.

You would want to use shared_ptr for pointer(s) that are responsible for the lifetime of your object and weak_ptr for the other pointers, which may become invalid. You'll see that weak_ptr has the validity check you're asking for built in.

Shmoopty
I haven't used shared_prt but as far as I understand it is a pointer which controls object's life time. I have opposite situation. I have an object which can delete itself upon receiving a message. I need those pointing to it to have a way to know they possess invalid pointer.
Jack
That's exactly the sort of case weak_ptr is made for. The weak_ptr will let the object die, and report invalidity if you later try and access the object through the weak_ptr. A much better solution than catching SIGSEGV!
timday
That's what I thought your situation was. The "delete me" message should reset the one-and-only shared_ptr. After that, all weak_ptr's made from that shared_ptr will know they are invalid. Take a look at the weak_ptr link for examples.
Shmoopty
A: 

Generally, regarding the pretty weird idea of "checking a non-NULL pointer for validity", have a look at this article: http://blogs.msdn.com/oldnewthing/archive/2006/09/27/773741.aspx ("IsBadXxxPtr should really be called CrashProgramRandomly")

oliver