Testing pointers for validity (C/C++)
Update for clarification: The problem is not with stale, freed or uninitialized pointers; instead, I'm implementing an API that takes pointers from the caller (like a pointer to a string, a file handle, etc.). The caller can send (in purpose or by mistake) an invalid value as the pointer. How do I prevent a crash?
You can't make that check. There is simply no way you can check whether a pointer is "valid". You have to trust that when people use a function that takes a pointer, those people know what they are doing. If they pass you 0x4211 as a pointer value, then you have to trust it points to address 0x4211. And if they "accidentally" hit an object, then even if you would use some scary operation system function (IsValidPtr or whatever), you would still slip into a bug and not fail fast.
Start using null pointers for signaling this kind of thing and tell the user of your library that they should not use pointers if they tend to accidentally pass invalid pointers, seriously :)
How to check if a pointer is valid?
The best bet if you must use raw pointers is to make sure that it is either a valid pointer or NULL. Then you can check if it is valid by checking if it is equal to NULL.
But to answer your question, you can catch these kinds of things with structured exception handling (SEH).
That being said, SEH is a bad idea.
testing for valid pointer in c++
*p = 0;
you probably meant
p = 0;
*p = 0 sets what the pointer points to, not the pointer
C++ Is it possible to determine whether a pointer points to a valid object?
No, you can't. Why? Because it would be expensive to maintain meta data about what constitutes a valid pointer and what doesn't, and in C++ you don't pay for what you don't want.
And you don't want to check whether a pointer is valid, because you know where a pointer comes from, either because it's a private part of your code that you control, or because you specified it in your external-facing contracts.
How to check pointer points to valid String in C
You cannot do this.
You can determine whether a char*
value is a null pointer or not, but if it's non-null, you cannot determine whether it's a valid pointer. You certainly can't do so portably; you probably can't do it non-portably either.
For example:
char *ptr = malloc(6);
strcpy(ptr, "hello");
// now ptr points to a valid string
free(ptr);
// now ptr doesn't point to a valid string -- but there's no way to test it
If you happen to know that the pointer is valid (or is either valid or null), you still can't do it. For example:
char buf[5] = "hello"; // not a string, since there's no '\0'
char *ptr = buf; // ptr points to valid data, but it's not a string
You can scan memory starting at *ptr
looking for a '\0'
string terminator, but you can't know when to stop looking. In this case, you might look at 5 bytes of memory and not find a '\0'
-- but what if ptr
pointed to a valid string that's 1000 characters long?
And in this case, it's entirely possible that there happens to be a '\0'
byte immediately after the array, which could make it appear that ptr
points to a valid string. (Accessing that 6th byte has undefined behavior. The worst consequence of undefined behavior is that it can appear to "work", which just means it's more difficult to track down the bug.)
The only way to determine whether a pointer points to a valid string is to write your code in a way that guarantees that it does. If it doesn't, it's not a problem you can detect after it occurred.
Can we check a pointer to make sure it is a valid address?
I think a valid pointer should have a valid object.
Yes, that's the definition of a valid pointer.
If we try to print out the object we verify if the pointer is valid.
Unfortunately, you can't. You can check whether the pointer is null; but if it wasn't initialised properly, or if it pointed to an object that's been destroyed, it will be neither valid nor null.
If you want a pointer that's smart enough to know whether it's valid, you'll need a smart pointer.
Fast way to check if file pointer points to a valid file
If a call to fopen
has succeeded, but you want to know whether you've just opened a file or something else, I know of two general approaches:
Use
fstat
on the file descriptor (orstat
on the same pathname you just opened), then inspect the mode bits.Attempt to seek on the file descriptor. If this works as expected it's probably a file; if it doesn't it's a pipe or a socket or something like that.
The code for (1) might look like
struct stat st;
fstat(fileno(fp), &st);
if(st.st_mode & S_IFMT) == S_IFREG)
/* it's a regular file */
To perform (2) I normally seek to offset 1, then test to see what offset I'm at. If I'm at 1, it's a seekable file, and I rewind to 0 for the rest of the program. But if I'm still at 0, it's not a seekable file. (And of course I do this once, right after I open the file, and record the result in my own flag associated with the open file, so the performance hit is minimal.)
How to judge whether the incoming buffer is valid in C++?
Don't. Just don't.
Even if you could find a way to check whether the pointer can safely be dereferenced, that doesn't mean it points where you think it does! It might point into your call stack, into your read-only code segment, into the static variables of some library that you're using, or any other place in memory that your program happens to have access to.
The responsibility of passing a valid pointer should be with the caller of the function. To make it harder for the caller to do something stupid, consider passing a std::vector &
or std::vector const &
instead.
Related Topics
Getting a File* from a Std::Fstream
Why Does Rand() Yield the Same Sequence of Numbers on Every Run
Defining Static Members in C++
How to Create a Generic Object Model For Use in Qml
When to Use Inline Function and When Not to Use It
How to Iterate Through Every File/Directory Recursively in Standard C++
Detecting Signed Overflow in C/C++
Why Not Non-Const Reference to Temporary Objects
Multithreading Program Stuck in Optimized Mode But Runs Normally in -O0
C++ Virtual Function from Constructor
C++ Member Initialization List
Why Are #Ifndef and #Define Used in C++ Header Files
When Do I Use a Dot, Arrow, or Double Colon to Refer to Members of a Class in C++
How to Correctly Implement Custom Iterators and Const_Iterators