Checking pointers

P

pinkfloydhomer

When a function is given a pointer, it is tempting to do an assert on
the pointer to see if it is not NULL. But even if it is not NULL, it
could still be invalid or wrong. What we really want to know is that it
points to memory that we have access to. How about doing this:

void f(int* p)
{
assert(*((char*)p) == *((char*)p);
}

To see if pointer points to something that I have access to?

Is there another way of do something like this?

/David
 
A

Abhi

If it is invalid it will still result in exception when we do *p i.e.
trying to access the memory...
 
F

Flash Gordon

When a function is given a pointer, it is tempting to do an assert on
the pointer to see if it is not NULL. But even if it is not NULL, it
could still be invalid or wrong. What we really want to know is that it
points to memory that we have access to. How about doing this:

void f(int* p)
{
assert(*((char*)p) == *((char*)p);

The compiler could optimise this away since it is always undefined
behaviour (if p is not a valid pointer) or true.

On systems where the compiler implements the test the most likely
results with an invalid pointer are either a crash (SIGSEGV on *nix) or
it returning true and you continuing with an invalid pointer.
}

To see if pointer points to something that I have access to?

Is there another way of do something like this?

This has been discussed here before. There is absolutely no portable way
to determine if a pointer is valid. If you want to know if it is
possible on a specific implementation then ask on a group dedicated to
that implementation.
 
J

junky_fellow

When a function is given a pointer, it is tempting to do an assert on
the pointer to see if it is not NULL. But even if it is not NULL, it
could still be invalid or wrong. What we really want to know is that it
points to memory that we have access to. How about doing this:

void f(int* p)
{
assert(*((char*)p) == *((char*)p);
}

To see if pointer points to something that I have access to?

Is there another way of do something like this?

/David

If p is not a valid address, accessing it will cause exception.
<OT>
On a unix system, the kernel posts signal SIGSEGV to the application
indication when it accesses any invalid address. So, first insatll
a handler for SIGSEGV. Do a setjmp() before varifying the address
and then do a longjump from the signal handler.
In embedded systems, you may replace the exception handler with that
of yours that would pass some information to the application
whether the address was valid/invalid.
</OT>
 
E

Eric Sosman

When a function is given a pointer, it is tempting to do an assert on
the pointer to see if it is not NULL. But even if it is not NULL, it
could still be invalid or wrong. What we really want to know is that it
points to memory that we have access to.

That's not really good enough. What you really want to
know is that the pointer points "where it ought to," which
is much harder to characterize. Using assorted non-portable
tricks you might be able to learn whether a pointer points to
a valid memory location, whether it's correctly aligned for
its type, whether the memory is readable and/or writeable,
and maybe other things, too. If these tests fail you may
conclude that a pointer is incorrect, but if they all pass
you still don't know if the pointer is "right."
How about doing this:

void f(int* p)
{
assert(*((char*)p) == *((char*)p);
}

To see if pointer points to something that I have access to?

If `p' doesn't have a valid pointer value, the attempt
to use it causes undefined behavior. (Another respondent
said "accessing it will cause exception," but he is wrong.
"An exception" is among the things that might happen -- but
it might not, too.) In other words, your test is reliable
only if `p' is valid; if `p' is invalid there is no telling
what might happen.
Is there another way of do something like this?

I can think of nothing portable. And, as I've suggested
above, I think the various non-portable tests you might be
able to make are at best half-measures. (Confession: I have
not personally used things like Purify or valgrind and cannot
speak to their effectiveness -- but certainly a "spot-check"
test unsupported by considerable additional machinery is of
limited effectiveness.)

C programmers find themselves doing a lot of "manual"
memory management. This has its good side (flexibility) and
its bad (susceptibility to error). The kind of test you
propose can detect some kinds of errors, but my impression
is that they are the minority: it's much more common to use
a "stale" pointer by mistake or to make an off-by-one error
and point to the neighbor of the intended object than it is
to pull a completely garbage pointer right out of the blue.
It may sound like a counsel of perfection, but I think the
only way to survive is discipline: you need to construct little
"mini-proofs" of correctness as you go along. It's not infallible
(so few things are), but it seems more effective than trying
to apply an unreliable test after the fact.
 
C

CBFalconer

Eric said:
That's not really good enough. What you really want to
know is that the pointer points "where it ought to," which
is much harder to characterize. Using assorted non-portable
tricks you might be able to learn whether a pointer points to
a valid memory location, whether it's correctly aligned for
its type, whether the memory is readable and/or writeable,
and maybe other things, too. If these tests fail you may
conclude that a pointer is incorrect, but if they all pass
you still don't know if the pointer is "right."

Such tricks depend on what the pointer is supposed to point to.
For example, in a doubly linked list, one can check that:

(p->next>-prev == p) && (p->prev->next == p)

(with suitable allowances for the ends of the list). My nmalloc
mechanism for DJGPP uses this sort of thing as self protection, and
it reduces the chance of a wild pointer destroying the entire
malloc arena.
 
K

Keith Thompson

If p is not a valid address, accessing it will cause exception.
<OT>
On a unix system, the kernel posts signal SIGSEGV to the application
indication when it accesses any invalid address. So, first insatll
a handler for SIGSEGV. Do a setjmp() before varifying the address
and then do a longjump from the signal handler.
In embedded systems, you may replace the exception handler with that
of yours that would pass some information to the application
whether the address was valid/invalid.
</OT>

As others have pointed out, there is no portable way to determine
whether a pointer is valid. There are a number of non-portable ways
to do this check (such has catching SIGSEGV) -- but that still leaves
the question of what to do once you've detected the error.

An invalid pointer almost certainly indicates a bug in your program.
Attempting to continue executing with a known bug could well cause
more damage. Very often, the best way to handle the bug is to let the
program die immediately, and let the operating system produce whatever
diagnostics it can. Then fix the bug, recompile, and try again -- or
submit a bug report and ask for your money back.

In some cases, you might want to do some cleanup before terminating
the program. For example, you might try to update and close any open
files to avoid losing too much information. This can still be
dangerous, though, if the bug can affect the cleanup code. It's often
better to write the program so it's always in a consistent state (for
example, any file are periodically updated); this will also handle
things like turning off the power while the program is running.

In some (but not all) safety-critical applications, shutting down the
program might be the worst thing you could do. For example, you might
have a choice between attempting to continue executing (perhaps in
some safe mode) and letting the airplane crash. In such cases, it
makes sense to use whatever system-specific means are available to
detect errors -- and then kick yourself for letting such an error get
into the production version of the program. (Many would question
whether C is an acceptable language for such an application.)
 
J

junky_fellow

Keith said:
As others have pointed out, there is no portable way to determine
whether a pointer is valid. There are a number of non-portable ways
to do this check (such has catching SIGSEGV) -- but that still leaves
the question of what to do once you've detected the error.

An invalid pointer almost certainly indicates a bug in your program.
Attempting to continue executing with a known bug could well cause
more damage. Very often, the best way to handle the bug is to let the
program die immediately, and let the operating system produce whatever
diagnostics it can. Then fix the bug, recompile, and try again -- or
submit a bug report and ask for your money back.

In embedded domain, sometimes it becomes necessary to check for the
validity of addressses. For eg, Suppose the user wants to set a
breakpoint at some address (the address being entered as an input by
the user) then it is necessary to validate that address because it
may be possible that user has given some invalid address.
Similarly, while taking memory dumps, the user address must be
validated.
But all this is platform specific.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,563
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top