The free() thing

T. William Wells bill at twwells.com
Thu Sep 14 12:20:55 AEST 1989


I posted a note on using a pointer after it was freed that seems to
have become lost. The point is that *any* dpANS compliant compiler,
on any system, may generate invalid code if you use a pointer after
it is freed. Here is how:

Free() is defined in the dpANS library. That being the case, the
compiler is free to assume that the pointer's value is not being used
legitimately after the call. It knows that the object to which the
pointer pointed no longer exists, so there is no valid use of the
pointer's value.

During code generation, it could mark the location the pointer is
stored in as dead right after the pointer's value is made available
for the free call, since it knows that there can be no legitimate
reason to access the value of the pointer.

Consider this fragment:

foo()
{
	char    *ptr;

	...
	free(ptr);
	if (ptr == 0) ...
}

Now, suppose that the (8086-targeted) compiler puts ptr into register
di and that the caller is responsible for saving and restoring
registers. For all the compilers I know of, the code that would be
generated would be something like:

	push    di      | save di for later
	push    di      | argument for free
	call    free
	pop     cx      | remove the argument
	pop     di      | restore di
	test    di,di   | check for zero

BUT, since the compiler "knows" that ptr is invalid after the free,
it doesn't need to do the first and last stack instructions. So if
the compiler were very smart, the code would now look like this:

	push    di      | argument for free
	call    free
	pop     cx      | remove the argument
	test    di,di   | check for zero

(Of course, if it were *really* clever it would issue a diagnostic
instead of the test instruction....)

Which, of course, isn't likely to do anything useful.

The segmented architecture argument has the weakness that no one
seems to really believe it. But you can bet that, since the dpANS
permits this, and given the competitive push for speed, someone is
going to write an optimizer that takes advantage of this little quirk
of the language.

And then that test is going to fail.

So if you want to write portable programs, you had better assume that
a freed pointer has no value that you should look at. Because it may
have no determinate value.

---
Bill                    { uunet | novavax | ankh | sunvice } !twwells!bill
bill at twwells.com



More information about the Comp.lang.c mailing list