From: crlstu4@bnr.ca (Goetz von Escher)
Subject: SUMMARY: Is pointer in my address space?
Keywords: process address space memory
Organization: Bell-Northern Research, Ottawa, Ontario, CANADA
Date: Tue, 13 Oct 92 23:24:36 GMT

Thanks to: Andrzej Bieszczad, Dan Senior, Barry Margolin, Eric Hildum,
           Thomas M. Breuel, Steve Clamage, Dwight Wilson, James A. Mullens
           David Kastrup, Stuart MacMartin

--------------------------------------------------------------------------------
ORIGINAL QUESTION WAS:
--------------------------------------------------------------------------------

<Goetz von Escher>:
Is there a way to find out if a pointer is a valid pointer in C/C++?
Or in other words: If I want to read a value in memory, how do I
know wether I can read the value at this address without causing
an exception (bus error, segmentation fault and that stuff)?

--------------------------------------------------------------------------------
SUMMARY OF DISCUSSION
--------------------------------------------------------------------------------

A lot of people mentioned that using an invalid pointer is a bug
that should be fixed not handled. I like the comment by

<Barry Margolin>:
Just because it's in your address space doesn't mean it's correct.  And in
fact, the pointers that point to random data in your address space are the
more dangerous ones; other pointers will at least cause a fault, so the
program will halt immediately rather than possibly producing incorrect
results.

Others mentioned that this questions does not belong to comp.lang.c++:

<Eric Hildum>:
This kind of a check is really an operating system issue, not a language
issue (at least, not in languages such as C and C++).

--------------------------------------------------------------------------------
SUMMARY OF PROPOSALS
--------------------------------------------------------------------------------

Difficult! I did not get too many concrete solutions. Here is what people wrote:

- in C++ you can test wether a pointer is NULL only
- to do this you have to trap the signals
- on the VAX: use the PROBE instruction
- keep track of allocated memory addresses (highest address, lowest address)
  and compare pointers to this range

--------------------------------------------------------------------------------
MY (QUICK AND DIRTY) SOLUTION
--------------------------------------------------------------------------------

To be able to continue with my work, I implemented a quick and dirty version
by myself. Yes I know setjmp/longjmp is ugly (Can somebody tell me why?). But
what do you think about this solution:


********************************************************************************
THE REST OF THIS FILE IS C++ SOURCE CODE
********************************************************************************
extern "C" {
#include <signal.h>
#include <setjmp.h>
}
#include <iostream.h>

jmp_buf env;       // memory to save the environment for setjmp/longjmp

//--------------------------------------------------------------------------
// myHandler - EXCEPTION HANDLER FOR isValidPointer()
//    This exception handler is installed only temporary in the function
//    isValidPointer. It does nothing but return 4.
//--------------------------------------------------------------------------
void myHandler(int sig, int code, struct sigcontext* scp, char* addr) {
   longjmp(env,4); // return 4
}

//--------------------------------------------------------------------------
// isValidPointer - test if pointer is in my process address space
//    return true (1) if pointer can be read without a segmentation fault
//    returns false (0) if pointer cannot be read
// WARNING: This function does not catch bus errors (maybe it should?)
//--------------------------------------------------------------------------
int isValidPointer(void* p) {
   int ret = 1;                                  // set default return value
   void* oldHandler = signal(SIGSEGV,myHandler); // install new handler
   if (setjmp(env)!=4) {                         // save environment for jmp
      char c = *((char*)p);                      // try reading the pointer
   } else {                                      // if it failed we are here
      ret = 0;                                   // set return value false
      if (oldHandler) signal(SIGSEGV,oldHandler);// install old handler
      else signal(SIGSEGV,SIG_DFL);              //    or default handler
   }
   return ret;                                   // return boolean
}

//--------------------------------------------------------------------------
// main - test program for function isValidPointer()
//--------------------------------------------------------------------------
main() {
   char g;
   cout<<"now executing:    \n";
   cout<<"isValidPointer((void*)1)  : "<<isValidPointer((void*)1)<<"\n";
   cout<<"isValidPointer((void*)&g) : "<<isValidPointer((void*)&g)<<"\n";
   cout<<"isValidPointer((void*)-1) : "<<isValidPointer((void*)-1)<<"\n";
   cout<<"we are back !!!!\n";
   cout<<"now lets see if we still can cause a REAL segmentation fault:\n";
   *((char*)0) = 99;
}


Newsgroups: comp.lang.c++