Run-time checking in C

Kaufer - Lopez - Pratap steve at endor.harvard.edu
Sat Dec 10 05:58:46 AEST 1988


I am just catching up on my net-mail, and have a comment on a subject discussed
a few days ago: run-time checking in the C language.

Warning: this is from a *>>> VERY BIASED SOURCE <<<*
i.e. I work on a product, Saber-C, that does run-time checking for C programs.

As mentioned before, the C language is a very difficult one in which to insert
run-time checking.  Just about every operation has some sort of checking
that can be done.  Arithmetic operations should check for over/underflow,
pointer operations should check for bad pointer values, function calls
should check the types and number of arguments, to name just a few.

Several attemtps have been made to add some of these checks to various 
compilers, (i.e. the data general compiler mentioned earlier, bcc, safe-c), 
but to do all of this checking thoroughly is just too much of 
a burden for a compiler.  

By way of specifics, it isn't good enough to catch a pointer out-of-bounds by
checking to see if it is outside of your data segment, the compiler
should check to see if it is outside 'the object pointed to'.
For many systems, this involved passing around the bounds of each object
with the pointer.  However, all of the existing
libraries and unix system call interfaces REQUIRE that pointers be
4 bytes (well, at least for 32 bit computers).  Users could either
recompile the libraries (and the unix kernal) with this checkout compiler
(sounds fun, right!?!), or interface routines can be developed that 
that convert between library code and the special run-time
checked code, in which case the boundary info is lost, and there go half your
pointer checks.  Obviously, these checks should also
work if the object pointed to is global, automatic or dynamically allocated.

Has anyone here ever been bitten by a 'memory trashed' bug?  Where the
core dump is far removed from wherever the bug was found?  
A pointer problem, right?  Well, bounds checking doesn't let that sort
of thing happen...

Another useful category for run-time checking is detecting 
memory inconsistencies:
	char *cp; 
	int i, j;
	i = 10;
	cp = (char *)&i;
	*cp = 'a';
	j = i;
This last line uses the value of 'i', which has been 'damaged' by 
the legal (if dubious) dereference of 'cp'.  
It is tough to imagine a compiler putting in checks on *EVERY* reference
to a memory location!

A simpler example would be:
	double d;
	union U { int i; double d; } u;
	u.i = 2;
	d = u.d;
Here we put an integer in the union, and then retrieve a double value.
Probably something the programmer wants to be notified about....

Saber-C catches these problems by using a C interpreter.
There is also a dynamic linker which allows interpreted code to be 
intermixed with object code, so that large projects can be debugged
efficiently.  I could obviously go on at length about all of the other
benifits of Saber-C, but thats another story...


	- Steve Kaufer
	kaufer%saber at harvard.edu
	harvard!saber!kaufer
	Saber Software, Inc.
	(617) 876-7636



More information about the Comp.lang.c mailing list