effect of free()

Chris Torek chris at mimsy.UUCP
Fri Sep 8 14:55:31 AEST 1989


In article <2054 at munnari.oz.au> ok at cs.mu.oz.au (Richard O'Keefe) writes:
>It is perfectly true that loading a (formerly valid, now invalid) address
>into an address register might cause a trap.  BUT there is no reason why
>a compiler has to translate "if (ptr == 0)" by loading ptr into an
>address register.

True enough.  (Indeed, all `if (ptr0 <compare> ptr1)' operations could
be done without loading either pointer into an address register, on all
machines of which I have ever heard.)  The problem is that the proposed
ANSI standard does not force compiler writers to do this.

Since everyone seems to want an example of a system on which

	ptr = malloc(size);
	if (ptr != NULL) {
		free(ptr);
		if (ptr == NULL) ... never gets here ...
		else ... never gets here either! ...
	}

might be the case, perhaps we should think for a moment and construct
one (an example, not a system).

First, we need a relatively common architecture that traps when
loading an invalid address into an address register.  How about the
80286?  It has `address' registers called CS, DS, ES, and SS, and
these trap when a bad segment is loaded and the processor is in
protected mode.

Now we need a way to have an invalid address happen.  So:


	void *malloc(size_t size) {
		segment_t seg = __syscall(_GET_SEGMENT);

		if (seg == _NO_SEGMENT) return NULL;
		return _SEG_TO_ADDR(seg);
	}

	void free(void *p) {
		if (__syscall(_RELEASE_SEGMENT(_ADDR_TO_SEG(p))))
			__runtime_abort("bad argument to free(): %lx",
			    (long)p);
	}

Now all we need is a sufficiently stupid compiler.  That is not
hard to write.  We construct one that, for every pointer construct,
compiles to something like this:

	; do something with a pointer
	xor	ax,ax			; check for segment 0 => nil
	or	ax,[bp + stackoff + 2]
	jz	Lptr_was_nil		; it was nil, so do not load it
	mov	es,[bp + stackoff + 2]	; not nil, load it.
	mov	di,[bp + stackoff]
	; what are we doing?  `ptr == nil'?  Oh, we already did that.
	jump	Lptr_was_not_nil
 Lptr_was_nil:
	; code...

(Please ignore any assembly syntax errors above; I have never used an
80x86 for any value of x, except perhaps as embedded controllers, where
I have never had to program them.  My only experience with 8086
assembly comes from looking over the operating systems class
assignments back when they were using IBM PCs.  [Now they are using
PS-halves, er, PS/2s, for that class.]  But I will say that I think the
8085 was nicer, and the Z80 had more reasonable opcodes.  [Both of
these were also descendents of the 4004.])

The only question the proposed ANSI standard can answer about the above
is whether this is a conforming implementation, as far as the specification
goes.  That is, is it conforming even though it does in fact generate
a trap on

	ptr = malloc(size); free(ptr); if (ptr == (char *)0)

even though we are not looking at *ptr?

The only *answer* the proposed standard gives is silence.  That is,
it does not say that this implementation is non-conformant (i.e., wrong).
Thus we must conclude that it does conform, and that the trap is
legal according to the proposed standard.

Standards (proposed or otherwise) generally do not say anything about
implementation quality, but I would have to agree that the implementation
described above is horrible.  It is not, however, outright illegal.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris at mimsy.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.lang.c mailing list