Memory (read) access violation handling in C

B

Bit byte

I have a structure defined like this:

struct foo
{
unsigned int magic ;
void *mydata ;
};



I have macros and defines like this :

#define MAGIC (0xFABF00D)
#define ISVALID_PTR(ptr) if(ptr)((ptr)->magic == MAGIC) ? 1 : 0) \ else 0

When a "bad pointer" - ( an arbitrary integer for example) is passed to
the macro, my library crashes (as one may well expect).

I am providing this C interface into another language, where there is a
great possibility of misuse and integers may be passed (accidentally) to
my functions, which use this validation macro above. I want my library
to be robust in the presence of such errors - in otherwords, I need to
be able to handle memory (READ) access violations gracefully and to be
able to recover from them - it is fairly trivial to do this in C++, but
I can't seem to find a way to do this in C.

Any solutions ?
 
P

pete

Bit said:
#define ISVALID_PTR(ptr) if(ptr)((ptr)->magic == MAGIC) ? 1 : 0)

That macro can't do anything.
It's part of an if statement, so it has no value,
and the statement has no side effects.
I would write that, this way:

#define ISVALID_PTR(ptr) (ptr != NULL && ptr -> magic == MAGIC)
 
K

Keith Thompson

Bit byte said:
I have a structure defined like this:

struct foo
{
unsigned int magic ;
void *mydata ;
};



I have macros and defines like this :

#define MAGIC (0xFABF00D)
#define ISVALID_PTR(ptr) if(ptr)((ptr)->magic == MAGIC) ? 1 : 0) \ else 0

When a "bad pointer" - ( an arbitrary integer for example) is passed
to the macro, my library crashes (as one may well expect).

I am providing this C interface into another language, where there is
a great possibility of misuse and integers may be passed
(accidentally) to my functions, which use this validation macro
above. I want my library to be robust in the presence of such errors -
in otherwords, I need to be able to handle memory (READ) access
violations gracefully and to be able to recover from them - it is
fairly trivial to do this in C++, but I can't seem to find a way to do
this in C.

There's no way in C to test whether a pointer is valid. You can
easily test whether a pointer is null, but if it's non-null garbage,
any attempt even to look at its value invokes undefined behavior.

<OT>I'm surprised that C++ provides a way to detect this; I would have
thought it also says this is undefined behavior.</OT>
 
S

spibou

Bit said:
I have a structure defined like this:

struct foo
{
unsigned int magic ;
void *mydata ;
};



I have macros and defines like this :

#define MAGIC (0xFABF00D)
#define ISVALID_PTR(ptr) if(ptr)((ptr)->magic == MAGIC) ? 1 : 0) \ else 0

When a "bad pointer" - ( an arbitrary integer for example) is passed to
the macro, my library crashes (as one may well expect).

I am providing this C interface into another language, where there is a
great possibility of misuse and integers may be passed (accidentally) to
my functions, which use this validation macro above. I want my library
to be robust in the presence of such errors - in otherwords, I need to
be able to handle memory (READ) access violations gracefully and to be
able to recover from them - it is fairly trivial to do this in C++, but
I can't seem to find a way to do this in C.

Any solutions ?

An arbitrary integer may happen to have a valid value for a pointer. So
I
don't think that there is a completely reliable way to check whether a
pointer
points to garbage. But if your concern is to check whether a pointer
points
to an area of memory from which your programme is not allowed to read
then the only possible **non-standard/non-portable** solution I can
think of is the following: it may be that your operating system sends
some
specific signal to a programme if it tries to read from memory it is
not
supposed to access. If this is the case then you should be able to do
something
useful using the signal() function. So I would suggest that you check
your
operating system's documentation.
 
D

Dave Thompson

There's no way in C to test whether a pointer is valid. You can
easily test whether a pointer is null, but if it's non-null garbage,
any attempt even to look at its value invokes undefined behavior.
Not in standard C, the topic here. However, the conversion from
pointer types to (suitable) integers is nonnormatively "intended to
be consistent with the addressing structure of the execution
environment" and on all or nearly so platforms even indeterminate or
dangling pointers do give _some_ value which can usefully be analyzed
but only in a platform-dependent way.
<OT>I'm surprised that C++ provides a way to detect this; I would have
thought it also says this is undefined behavior.</OT>

Standard C++ does not. It does however provide syntax and mechanism
for exceptions, and _some_ implementations which are able to catch
invalid memory accesses, or other 'hardware' faults like zerodivide,
choose to have them raise platform-defined exceptions -- which can
then be handled using basically standard constructs.

_On these platforms_ using (standard C) signal() to establish a
handler for SIGSEGV or similar is very likely to work as well.

As already noted this is only a half-measure; on almost all systems it
is trivial to construct, and often easy to get by accident, pointer
values which don't cause an immediate fault but are nonetheless
invalid and when used cause horribly bad results. (I once had a really
bad Heisenbug of this type; if the program was run under the debugger
the invalid pointer it used happened to be benign, but if run without
the debugger it got a different invalid pointer which caused a crash.)

- David.Thompson1 at worldnet.att.net
 

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

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,008
Latest member
HaroldDark

Latest Threads

Top