Testing pointers for validity (C/C++)

2019-01-02 15:28发布

Is there any way to determine (programatically, of course) if a given pointer is "valid"? Checking for NULL is easy, but what about things like 0x00001234? When trying to dereference this kind of pointer an exception/crash occurs.

A cross-platform method is preferred, but platform-specific (for Windows and Linux) is also ok.

Update for clarification: The problem is not with stale/freed/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?

28条回答
心情的温度
2楼-- · 2019-01-02 16:13

On Win32/64 there is a way to do this. Attempt to read the pointer and catch the resulting SEH exeception that will be thrown on failure. If it doesn't throw, then it's a valid pointer.

The problem with this method though is that it just returns whether or not you can read data from the pointer. It makes no guarantee about type safety or any number of other invariants. In general this method is good for little else other than to say "yes, I can read that particular place in memory at a time that has now passed".

In short, Don't do this ;)

Raymond Chen has a blog post on this subject: http://blogs.msdn.com/oldnewthing/archive/2007/06/25/3507294.aspx

查看更多
余生无你
3楼-- · 2019-01-02 16:14

Firstly, I don't see any point in trying to protect yourself from the caller deliberately trying to cause a crash. They could easily do this by trying to access through an invalid pointer themselves. There are many other ways - they could just overwrite your memory or the stack. If you need to protect against this sort of thing then you need to be running in a separate process using sockets or some other IPC for communication.

We write quite a lot of software that allows partners/customers/users to extend functionality. Inevitably any bug gets reported to us first so it is useful to be able to easily show that the problem is in the plug-in code. Additionally there are security concerns and some users are more trusted than others.

We use a number of different methods depending on performance/throughput requirements and trustworthyness. From most preferred:

  • separate processes using sockets (often passing data as text).

  • separate processes using shared memory (if large amounts of data to pass).

  • same process separate threads via message queue (if frequent short messages).

  • same process separate threads all passed data allocated from a memory pool.

  • same process via direct procedure call - all passed data allocated from a memory pool.

We try never to resort to what you are trying to do when dealing with third party software - especially when we are given the plug-ins/library as binary rather than source code.

Use of a memory pool is quite easy in most circumstances and needn't be inefficient. If YOU allocate the data in the first place then it is trivial to check the pointers against the values you allocated. You could also store the length allocated and add "magic" values before and after the data to check for valid data type and data overruns.

查看更多
倾城一夜雪
4楼-- · 2019-01-02 16:14

these links may be helpful

_CrtIsValidPointer Verifies that a specified memory range is valid for reading and writing (debug version only). http://msdn.microsoft.com/en-us/library/0w1ekd5e.aspx

_CrtCheckMemory Confirms the integrity of the memory blocks allocated in the debug heap (debug version only). http://msdn.microsoft.com/en-us/library/e73x0s4b.aspx

查看更多
余生无你
5楼-- · 2019-01-02 16:17

I've got a lot of sympathy with your question, as I'm in an almost identical position myself. I appreciate what a lot of the replies are saying, and they are correct - the routine supplying the pointer should be providing a valid pointer. In my case, it is almost inconceivable that they could have corrupted the pointer - but if they had managed, it would be MY software that crashes, and ME that would get the blame :-(

My requirement isn't that I continue after a segmentation fault - that would be dangerous - I just want to report what happened to the customer before terminating so that they can fix their code rather than blaming me!

This is how I've found to do it (on Windows): http://www.cplusplus.com/reference/clibrary/csignal/signal/

To give a synopsis:

#include <signal.h>

using namespace std;

void terminate(int param)
/// Function executed if a segmentation fault is encountered during the cast to an instance.
{
  cerr << "\nThe function received a corrupted reference - please check the user-supplied  dll.\n";
  cerr << "Terminating program...\n";
  exit(1);
}

...
void MyFunction()
{
    void (*previous_sigsegv_function)(int);
    previous_sigsegv_function = signal(SIGSEGV, terminate);

    <-- insert risky stuff here -->

    signal(SIGSEGV, previous_sigsegv_function);
}

Now this appears to behave as I would hope (it prints the error message, then terminates the program) - but if someone can spot a flaw, please let me know!

查看更多
不再属于我。
6楼-- · 2019-01-02 16:18

Preventing a crash caused by the caller sending in an invalid pointer is a good way to make silent bugs that are hard to find.

Isn't it better for the programmer using your API to get a clear message that his code is bogus by crashing it rather than hiding it?

查看更多
情到深处是孤独
7楼-- · 2019-01-02 16:18

This article MEM10-C. Define and use a pointer validation function says it is possible to do a check to some degree, especially under Linux OS.

查看更多
登录 后发表回答