From: sjm@bcrki65.bnr.ca (Stuart MacMartin)
Subject: Re: Is pointer in my address space?
Keywords: process address memory pointer
Organization: Bell-Northern Research Ltd., Ottawa, Canada
Date: Tue, 13 Oct 1992 13:50:44 GMT

In article <dak.718927004@tabaqui> dak@tabaqui.informatik.rwth-aachen.de (David Kastrup) writes:
>crlstu4@bnr.ca (Goetz von Escher) writes:
>
>
>>Hi there!
>
>>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)?
>
>>Goetz
> if you have to check whether you can store your values, you have a lousy program.
>One does not just use any memory which does not cause a violation, you
>know. If you really are into muck, try catching the segmentation violation,
>Trying in any way to ignore or circumvent it is
>madness. Be glad the MMU is there to protect you from your folly!

Oh, come on now!  Don't be silly.  You obviously have never provided 
utility routine/class support to other programmers.  During development
of code that uses utility code, programmers will make mistakes that
lead to runtime errors.  The earlier these errors are detected, and the
more information the routine can provide the programmer without the
programmer having to go into a debugger, the easier it is to determine
what the problem is.  Just allowing the seg fault means that the programmer
has to do work to figure out what happened.  And worse, he might have to
consult with the programmer of the code where the seg fault happened,
even if the seg fault is due to some other error.  As a utility routine
programmer, I have learned that the more information I can provide my
users and the earlier I can detect a run-time problem, the less consulting
I have to do.

There are several times when this is useful in C.  (I'll get to C++ in
a moment.)  There might be others, and you might dispute these.  They
are just examples to justify wanting to be able to check addresses to
see if they are legal.

1.  (This is obsoleted by ANSI type checking, but not all of us have
    the luxury of running ANSI all the time).  A program is expecting
    the address of something, but programmers sometimes pass the 
    something instead.  If the pointer is non-NULL and not valid, it is
    useful to check to see if this is the common error - and then to tell
    the programmer in an error message exactly what is wrong.

2.  The user is passing the address of a structure.  This structure 
    contains junk, for whatever reason.  It might be the wrong structure
    (not much of a problem in strongly-typed systems, but possible using casts);
    it might have been allocated but not initialized (not much of a
    problem in C++), or it might have been overwritten by some other code
    (e.g. it was already freed).  It is often a good idea for the receiving
    routine to do a quick sanity check on the structure.  Checking addresses
    can be part of this check.

3.  If the end-user has an embedded programming language that is not C
    or C++, there is an interface between the two.  If the end-user of
    the application tries to use an object that has been deleted, then
    this must be reported to him correctly, and cleanly.  Sometimes this
    can involve checking an address before dereferencing.  This is not
    a run-time error.  This is a condition that must be handled by the
    application.  If the application allows the seg-fault, then even
    with an interrupt handler, the illegal input is not being detected
    correctly.

In C++, situation 3 above still might apply. Also, testing for illegal
addresses might be useful in a object sanity test (object, not class),
where each object checks itself to see if it is sane, and reports 
insanity where it finds it.  One thing to test for would be legal addresses
in pointers.  Sounds like a useful debugging tool to me, as well as useful
in detecting bad parameters due to bad casts (situation 2 above)!

Catching seg faults is a good idea to make robust production code, but
that is not the point.  People do not always state all of their reasons
for wanting something when they ask a question.  Maybe I misread your tone,
but it would have been more polite to ask if there was a good reason for
doing what was asked instead of just assuming that catching seg faults
is the only good way of doing things.
========================================================================

There is one trick I have used in the past, but it is only good in
limited circumstances.  Perhaps it could be generalized for C++ and new
or handled in constructors.  I kept track of the smallest and largest
addresses allocated for my purposes.  Then whenever my code is called
with an address I was supposed to have allocated, I could check to see
if it is in a legal range.  On the architectures we currently use, 
dereferencing an address in this range is legal.

This does not handle cases where the caller generates his own addresses,
on the stack or using his own heap management.  You might be able to
check sbrk(0) or _end.

If the class has a static lowestAddress_ and highestAddress_ kept up 
by the constructor, then this check can be made - if the type of the
object that the address points to is known.  However, it might not
catch illegal addresses that lie between the stack and the heap.

If there are not a huge number of objects, it is often useful to have
a collection of all currently operating objects of that class.  This
is easily done by having a static collection associated with the class,
and a class method that queries if the object is of that type.
However, I think we ought to spend more time looking at run-time type
checking before we jump on any one arbitrary solution.

Stuart
--
: Stuart MacMartin                                    email: sjm@bnr.ca      :
: Bell-Northern Research                              phone: (613) 763-5625  :
: PO Box 3511, Stn C, Ottawa, K1Y-4H7, CANADA    Standard disclaimers apply. :
Newsgroups: comp.lang.c++