[comp.lang.c] The free

bill@twwells.com (T. William Wells) (09/14/89)

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@twwells.com

lehners@uniol.UUCP (Joerg Lehners) (09/15/89)

bill@twwells.com (T. William Wells) writes:

>[a bit deleted]

>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.

>[description and example C and 8086 code deleted]

I don't like this idea at all.
Don't hardcode any (even standard) functions into the compiler.
What about writing my own free() function, possibly with a completly
different semantic ?
The compiler has no chance to detect such a case on most systems, because
compilation and linkage are independent (is this independence standardized
at all ??).
On the machine I use, there are such things of compiler detected functions
for floating point operations: whenever I declare a function sin()
(arguments aren't checked -- no prototyping) WITH return value double
(as done in math.h) then the compiler generates some code for the
floating point coprocessor inline. Such things are evil enough.
But it seems the only way to make floating point operation real fast.

I wan't to feel free about naming my function's. Even overriding of
standardized functions should by possible (in my eyes).
(I know about the problems doing this when using other standardized
functions like the ones from stdio).

What does the standard say about standardized function overriding ?
Maybe one have to distingish between
   a.) C-Compiler: just the C keywords are reserved,
       function overriding possible and possible more.
   b.) C-System (C-Compiler plus standardized function package [often
       called 'library']: C keywords reserved; return type, argument types
       of standardized functions reserved; and more.

>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.
I agree. The usabilty of a pointer after free() upto the next malloc
package function call should never have been a feature.

  Joerg
--
/ Joerg Lehners                       | Fachbereich 10 Informatik ARBI   \
|                                     | Universitaet Oldenburg           |
| BITNET/EARN: 066065@DOLUNI1.BITNET  | Ammerlaender Heerstrasse 114-118 |
\ UUCP/Eunet:  lehners@uniol.uucp     | D-2900 Oldenburg                 /

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/15/89)

In article <841@uniol.UUCP> lehners@uniol.UUCP (Joerg Lehners) writes:
>Don't hardcode any (even standard) functions into the compiler.
>What about writing my own free() function, possibly with a completly
>different semantic ?

You absolutely must NOT do that in a hosted implementation.  Several
library routines may depend, not only on the documented semantics of
an external function named free(), but also on implementation-specific
internal properties of the free() implementation.  If you provide your
own external function named free(), you can break the implementation.

>What does the standard say about standardized function overriding ?

A program that does that is not strictly conforming.

>Maybe one have to distingish between
>   a.) C-Compiler: just the C keywords are reserved,
>       function overriding possible and possible more.
>   b.) C-System (C-Compiler plus standardized function package [often
>       called 'library']: C keywords reserved; return type, argument types
>       of standardized functions reserved; and more.

The Standard provides for two forms of conforming implementation:
"hosted" (for which the standard headers and standard library are
provided), and "free-standing" (which provides only minimal header
and library support).

henry@utzoo.uucp (Henry Spencer) (09/16/89)

In article <841@uniol.UUCP> lehners@uniol.UUCP (Joerg Lehners) writes:
>What does the standard say about standardized function overriding ?

The answer is a little complicated.  Assuming you just want to use a
standard function's name for your own purposes, you can always do this
provided (a) it doesn't begin with __ or _[A-Z], and (b) you do not
#include the standard header declaring that function.  If either of these
restrictions is violated, behavior is "undefined", i.e. it's up to your 
compiler and it's not portable.

If what you want is to supply, say, your own atof() function, *and* have
[say] scanf() use it, there is no portable way to do this.  ANSI C
essentially demands that scanf() not call atof() at all, but some internal
version with a name in the implementation-reserved name space (see clause
(a) above).  This is so you can innocently re-use the name, as above,
without breaking scanf().  Your compiler *might* permit you to override
the function scanf() is using, but the name will be implementation-specific
and the overriding will violate clause (a) above.

>   a.) C-Compiler: just the C keywords are reserved,
>       function overriding possible and possible more.
>   b.) C-System (C-Compiler plus standardized function package [often
>       called 'library']: C keywords reserved; return type, argument types
>       of standardized functions reserved; and more.

It is not necessarily possible for an implementation to make a clean split
between the two, since some of the standard functions may be wired into
the compiler.  ANSI C does permit that, subject to the requirement that
the relevant headers be #included, so that innocent name re-use is not
an issue.  X3J11 was not at all keen on having multiple versions of C,
so it generally didn't provide the sort of choice you suggest.  (It did
end up being talked into providing one choice, between "hosted" and
"free-standing" implementations, which has some similarity to your request
but isn't the same thing.)
-- 
V7 /bin/mail source: 554 lines.|     Henry Spencer at U of Toronto Zoology
1989 X.400 specs: 2200+ pages. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

bill@twwells.com (T. William Wells) (09/16/89)

In article <841@uniol.UUCP> lehners@uniol.UUCP (Joerg Lehners) writes:
: I don't like this idea at all.
: Don't hardcode any (even standard) functions into the compiler.
: What about writing my own free() function, possibly with a completly
: different semantic ?

Much too late. The dpANS has given compiler writers licence to do
pretty much whatever they want in order to implement the functions
that are specified in the library section of the standard. This
doesn't mean that you won't be able to write your own free with
whatever semantics you want, but it does mean that it won't be
portable and it does mean that you will have no right to complain if
you can't make it work with some conforming compiler.

: The compiler has no chance to detect such a case on most systems, because
: compilation and linkage are independent (is this independence standardized
: at all ??).

However, the dpANS does give the compiler writer the means whereby he
can pretty much enforce this if he really wants to. For example, the
compiler writer could give a compile error if you named an external
function or external variable "free".

: What does the standard say about standardized function overriding ?

You can't portably override the functions in the library. Moreover,
there is a whole host of names that you can't use portably in certain
circumstances. I've got a list somewhere, perhaps I'll dig it out if
no one else posts one.

BTW, I too am not very happy about this: it effectively adds a whole
bunch of keywords to the language. Some of which one has no reason to
know exists. Well, it is much too late, and I haven't a suggestion to
fix it; I thought I did, but on further inspection, discovered a
fatal flaw. So now I'll just grumble about this language deficiency
and learn to live with it. (Oh yes, Standard C is much better about
this than K&R C: at least with Standard C you can look up in one
document the names you have to beware of; with K&R C you have to know
the names on every system you want to be portable to. And hope they
don't change without warning.)

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

barmar@think.COM (Barry Margolin) (09/16/89)

In article <11073@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>In article <841@uniol.UUCP> lehners@uniol.UUCP (Joerg Lehners) writes:
>>Don't hardcode any (even standard) functions into the compiler.
>>What about writing my own free() function, possibly with a completly
>>different semantic ?
>You absolutely must NOT do that in a hosted implementation.  Several
>library routines may depend, not only on the documented semantics of
>an external function named free(), but also on implementation-specific
>internal properties of the free() implementation.  If you provide your
>own external function named free(), you can break the implementation.

I thought implementation-provided libraries were required to use an
internal, underscore-prefixed name for all the standard library
functions, precisely to allow users to override the normal names.

>>What does the standard say about standardized function overriding ?
>
>A program that does that is not strictly conforming.

I thought you were allowed to do this, provided you first #undefine
the name.  Implementations are permitted to implement any of the
standard library functions as macros; if an implementation wished to
open-code certain library calls, it would define them as macros for
implementation-dependent keywords (in the underscore-prefixed
namespace, which the standard explicitly reserves for the
implementation) which are recognized by the compiler.

I remember these rules being discussed quite a bit a few years ago.
Did they not make it into the pANS?

Barry Margolin
Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

garys@bunker.UUCP (Gary M. Samuelson) (09/16/89)

In article <1989Sep14.022055.5961@twwells.com> bill@twwells.com (T. William Wells) writes:
>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.

I disagree.  For purposes of debugging, I have written my own
functions to call malloc() and free().  Mymalloc() calls malloc()
and records the pointer returned.  Myfree() checks to make sure that
(1). the pointer I want to free() was one originally obtained by
mymalloc(), and (2) that it has not already been released by myfree().
I claim that this is a valid use for a pointer which no longer points
to anything.

>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.

No compiler has any business changing the value of a variable
I have declared, except when I have written code to do so.
But even so, suppose there was another copy of that same pointer
in another variable?  How will the compiler know about that one?

>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.

Notice to compiler vendors:
No compiler I want to buy or use is going to exhibit this behavior.
If I want to examine a pointer, I better be able to.

As someone else has said, some day there will be two kinds of C
compiler: standard-conforming, and useful.

Gary Samuelson

scjones@sdrc.UUCP (Larry Jones) (09/17/89)

In article <1989Sep15.183248.2955@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) writes:
> In article <841@uniol.UUCP> lehners@uniol.UUCP (Joerg Lehners) writes:
> >What does the standard say about standardized function overriding ?
> 
> The answer is a little complicated.  Assuming you just want to use a
> standard function's name for your own purposes, you can always do this
> provided (a) it doesn't begin with __ or _[A-Z], and (b) you do not
> #include the standard header declaring that function.  If either of these
> restrictions is violated, behavior is "undefined", i.e. it's up to your 
> compiler and it's not portable.

That's true provided that you do not use it for an external
variable or function.  The names of library routines are reserved
in the external name space and may not be redefined reguardless
of whether you #include the associated header.

> ANSI C
> essentially demands that scanf() not call atof() at all, but some internal
> version with a name in the implementation-reserved name space (see clause
> (a) above).

Nope, standard library routines are at liberty to call other
standard library routines at will.  What they may NOT do is call
anything OTHER than a standard library routine unless it has a
reserved name as in (a) above.
----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@SDRC.UU.NET
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150-2789             AT&T: (513) 576-2070
"I have plenty of good sense.  I just choose to ignore it."
-Calvin

bill@twwells.com (T. William Wells) (09/17/89)

In article <1989Sep15.183248.2955@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
: In article <841@uniol.UUCP> lehners@uniol.UUCP (Joerg Lehners) writes:
: >What does the standard say about standardized function overriding ?
:
: The answer is a little complicated.  Assuming you just want to use a
: standard function's name for your own purposes, you can always do this
: provided (a) it doesn't begin with __ or _[A-Z], and (b) you do not
: #include the standard header declaring that function.  If either of these
: restrictions is violated, behavior is "undefined", i.e. it's up to your
: compiler and it's not portable.

The name must also not have external linkage. 4.1.2:

"All external identifiers declared in any of the headers are reserved,
whether or not the associated header is included."

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

henry@utzoo.uucp (Henry Spencer) (09/17/89)

In article <7513@bunker.UUCP> garys@bunker.UUCP (Gary M. Samuelson) writes:
>No compiler has any business changing the value of a variable
>I have declared, except when I have written code to do so.
>But even so, suppose there was another copy of that same pointer
>in another variable?  How will the compiler know about that one?

You have misunderstood completely.  The problem is not that the value of
the pointer variable might change.  The problem is that doing anything
with that value might cause a trap once it no longer points to valid
storage.  On many machines, pointers are just integer-like bit patterns
that you can diddle arbitrarily so long as you don't try to indirect
through them... but on *some* machines, they are heavily magical, the
hardware *knows* they point to something, and a pointer that no longer
points to anything valid is a dangerous object that might blow up in
your hands.  A maximally portable program must not mess with such
pointers.  This is a *fact*; the ANSI C standard just recognizes it.

>Notice to compiler vendors:
>No compiler I want to buy or use is going to exhibit this behavior.
>If I want to examine a pointer, I better be able to.

Your compiler vendors should have no problem satisfying this restriction
if you restrict your computer activities to the large-but-limited class of
well-behaved machines.  Some of us think this is a silly and unnecessary
restriction, especially for a supposedly-professional programmer.  In any
case, a language standard must avoid such restrictions as much as humanly
possible.
-- 
V7 /bin/mail source: 554 lines.|     Henry Spencer at U of Toronto Zoology
1989 X.400 specs: 2200+ pages. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

bill@twwells.com (T. William Wells) (09/17/89)

In article <7513@bunker.UUCP> garys@bunker.UUCP (Gary M. Samuelson) writes:
: In article <1989Sep14.022055.5961@twwells.com> bill@twwells.com (T. William Wells) writes:
: >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.
:
: I disagree.

So what? The standard defines what constitutes validity. And *it*
says that, once you've freed the pointer, if you do anything with it,
the results are undefined. You *may* get away with it, on some
implementation, or with some particular combination of compiler
flags. Or you may not. But whatever, it is always "getting away with".
It should not be presumed to be portable.

: >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.
:
: No compiler has any business changing the value of a variable
: I have declared, except when I have written code to do so.

Baloney. The compiler may do whatever is not inconsistent with the
language specification. Many compilers already change variables
behind your back. For example, there are compilers that determine
when a variable is no longer in use and, if there s another variable
that can use the same memory, will make them share the same location;
change the second variable and you change the first. My example with
free() is just another way the compiler vendor might do this.

: But even so, suppose there was another copy of that same pointer
: in another variable?  How will the compiler know about that one?

It won't likely. Which increases the probability of your getting away
with using it, though it does not make it unity. The compiler vendor
is not obligated to prevent you from doing something stupid.

: >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.
:
: Notice to compiler vendors:
: No compiler I want to buy or use is going to exhibit this behavior.
: If I want to examine a pointer, I better be able to.

Notice to compiler vendors:
I will judge compilers on compliance to the standard first, and
quality of implementation second. Speed is an important consideration
and, since *I* won't do stupid things like look at pointers when I'm
not supposed to, go ahead and trash freed pointers. Now, I'll admit
that I'd like a compiler option that turns off this optimization, but
I won't insist.

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

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/17/89)

In article <1989Sep15.183248.2955@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>In article <841@uniol.UUCP> lehners@uniol.UUCP (Joerg Lehners) writes:
>>What does the standard say about standardized function overriding ?
>The answer is a little complicated.  Assuming you just want to use a
>standard function's name for your own purposes, you can always do this
>provided (a) it doesn't begin with __ or _[A-Z], and (b) you do not
>#include the standard header declaring that function.

No, that's wrong.  All identifiers in section 4 with external linkage
(e.g. library function names) are reserved whether or not the associated
header is included.  It's only macros that are not reserved when the
header is not included.  See 4.1.2.1.

>ANSI C essentially demands that scanf() not call atof() at all, ...

No, in fact one of the main reasons the standard functions are reserved
is so the implementation of other standard library routines may safely
use them.  What you were saying is true only of NON-standard library
functions such as read().  "read" as an external identifier is reserved
for the application's own use; the standard library implementation must
not invoke the application's read() function (or data object!) in place
of whatever it is expecting to use to read from files.  Thus, POSIX
implementations of Standard C will have library routines such as scanf()
invoking __read() or some such reserved name instead.

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/17/89)

In article <29562@news.Think.COM> barmar@think.COM (Barry Margolin) writes:
>I thought implementation-provided libraries were required to use an
>internal, underscore-prefixed name for all the standard library
>functions, precisely to allow users to override the normal names.

No, in fact (strictly conforming) programs are PROHIBITED from
attempting to override the standard library function names.

>I remember these rules being discussed quite a bit a few years ago.
>Did they not make it into the pANS?

What made it into the pANS is what I said.  It was certainly discussed
in detail by X3J11 and that's what they decided.  I fully support this
decision.  There are good reasons for this constraint.

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/17/89)

In article <7513@bunker.UUCP> garys@bunker.UUCP (Gary M. Samuelson) writes:
>I disagree.  For purposes of debugging, I have written my own
>functions to call malloc() and free().  Mymalloc() calls malloc()
>and records the pointer returned.  Myfree() checks to make sure that
>(1). the pointer I want to free() was one originally obtained by
>mymalloc(), and (2) that it has not already been released by myfree().
>I claim that this is a valid use for a pointer which no longer points
>to anything.

I too have implemented such a safety-checking malloc/free wrapper,
and it seems to me that yours must be making a mistake.  You should
be checking only that the pointer fed to myfree() is one CURRENTLY
HANDED OUT by myalloc(), not that it has never previously been fed
to myfree().  As you malloc/free/malloc/free/..., eventually the same
pointer values come around again.  Having been previously freed does
not mean that a pointer value is not currently being used correctly,
because it may have been returned by a subsequent malloc().

The safety-checking malloc/free wrapper will not work portably IF
in fact there is pointer abuse, because of the inability to safely
inspect invalid pointer values in some environments.  It will work
in all environments so long as no pointer abuse occurs.  Thus it is
handy for debugging applications in an environment where invalid
pointers are safe to inspect, later porting the debugged application
to a more fussy environment.

>But even so, suppose there was another copy of that same pointer
>in another variable?  How will the compiler know about that one?

It can't.  The example this is a response to was misleading.

>As someone else has said, some day there will be two kinds of C
>compiler: standard-conforming, and useful.

It was an equally stupid thing for someone else to have said.

The Standard does not require that an implementation prevent you
from looking at invalid pointer values.  It merely permits C
implementations FOR WHICH THAT IS THE NATURAL BEHAVIOR to do so.
Those implementations probably would have done so in the absence
of a C standard.

Your assumption that it is safe to inspect an invalid pointer is
nonportable.  That has nothing to do with the proposed Standard.

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/17/89)

In article <1989Sep15.202109.4888@twwells.com> bill@twwells.com (T. William Wells) writes:
>BTW, I too am not very happy about this: it effectively adds a whole
>bunch of keywords to the language. Some of which one has no reason to
>know exists. Well, it is much too late, and I haven't a suggestion to
>fix it; I thought I did, but on further inspection, discovered a
>fatal flaw. So now I'll just grumble about this language deficiency
>and learn to live with it.

It would have been trivial for the Standard to have "fixed" this;
all standard library functions could have been given names starting
with an underscore, for example.  I personally would have preferred
that, along with reengineering the specs for many of the functions.
Suggestions along these lines were made, but it was deemed outside
X3J11's charter (namely, to standardize existing practice).

henry@utzoo.uucp (Henry Spencer) (09/17/89)

In article <11084@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>No, that's wrong.  All identifiers in section 4 with external linkage
>(e.g. library function names) are reserved whether or not the associated
>header is included.  It's only macros that are not reserved when the
>header is not included.  See 4.1.2.1.

I saw 4.1.2.1; in fact I spent quite some time studying it before composing
that answer.  I'm willing to concede that I was wrong, but I'm not happy
about the wording of the clauses touching on this issue; it's unfortunate
that it's too late for fixes.

(Please don't tell me that it's obvious what they mean.  Sure it's obvious,
if you already know what's intended.  If you go into it with a completely
open mind and try to find an explicit statement that definitively rules out
the wrong interpretation, it's not quite so obvious.  I'm beginning to think
that all major standards should have the equivalent of POSIX's "Weirdnix"
contest before they are cast in concrete; unless you deliberately *try* to
misconstrue the wording, it's not easy to find the places where there are
hidden assumptions.)

(The key assumption, by the way, is that all those library function names
in section 4 are really meant to be names with external linkage.  This is
hinted at but never quite explicitly said.)
-- 
"Where is D.D. Harriman now,   |     Henry Spencer at U of Toronto Zoology
when we really *need* him?"    | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

bill@twwells.com (T. William Wells) (09/18/89)

In article <11092@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
: In article <1989Sep15.202109.4888@twwells.com> bill@twwells.com (T. William Wells) writes:
: >BTW, I too am not very happy about this: it effectively adds a whole
: >bunch of keywords to the language. Some of which one has no reason to
: >know exists. Well, it is much too late, and I haven't a suggestion to
: >fix it; I thought I did, but on further inspection, discovered a
: >fatal flaw. So now I'll just grumble about this language deficiency
: >and learn to live with it.
:
: It would have been trivial for the Standard to have "fixed" this;
: all standard library functions could have been given names starting
: with an underscore, for example.  I personally would have preferred
: that, along with reengineering the specs for many of the functions.
: Suggestions along these lines were made, but it was deemed outside
: X3J11's charter (namely, to standardize existing practice).

Yeah. I'd have preferred something like that, but I'll also have to
agree with X3J11. Such is life.

My own suggestion was to make the names reserved only if the
appropriate header file was included. The fatal flaw is what happens
when you use someone else's library: you have (and should have) no
knowledge or control over what that library includes. Thus any
program that uses anything other than the Standard C library (which
is likely to be most of them) is going to have to assume that all the
names are reserved anyway. Thus this suggestion would add little or no
utility while inconveniencing the implementer a whole lot.

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

richard@aiai.ed.ac.uk (Richard Tobin) (09/19/89)

In article <11073@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>In article <841@uniol.UUCP> lehners@uniol.UUCP (Joerg Lehners) writes:
>>Don't hardcode any (even standard) functions into the compiler.
>>What about writing my own free() function, possibly with a completly
>>different semantic ?
>
>You absolutely must NOT do that in a hosted implementation.  Several
>library routines may depend, not only on the documented semantics of
>an external function named free(), but also on implementation-specific
>internal properties of the free() implementation.  

This is a real pain for programs (like interpreters for other languages)
that need to keep track of just what memory is in use.  A helpful
implementation would at least provide a way of producing code that
relied only on the advertised semantics of malloc(), etc, perhaps by
means of a compiler flag.

[Incidentally, if Joerg Lehners really wants "completely different"
semantics for free - rather than just say keeping a note of whats been
freed in addition to freeing the block - then he's going to lose!]

I hope that this will be treated as a "quality of implementation"
issue.

-- Richard

-- 
Richard Tobin,                       JANET: R.Tobin@uk.ac.ed             
AI Applications Institute,           ARPA:  R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk
Edinburgh University.                UUCP:  ...!ukc!ed.ac.uk!R.Tobin

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/20/89)

In article <902@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes:
>This is a real pain for programs (like interpreters for other languages)
>that need to keep track of just what memory is in use.  A helpful
>implementation would at least provide a way of producing code that
>relied only on the advertised semantics of malloc(), etc, perhaps by
>means of a compiler flag.
[...]
>I hope that this will be treated as a "quality of implementation"
>issue.

I don't understand your concern.  malloc()/realloc()/free() are
provided by the (hosted) C implementation and must meet the
specifications.  Details of the way these and other functions are
implemented are, and must be, left up to the implementor's discretion.
Because a strictly conforming program cannot take cognizance of
implementation-specific details, they needn't be of concern.

A program can wrap the system-provided malloc()/realloc()/free() with
its own bookkeeping module, if desired, but strict standard
conformance (or maximal portability) requires that it not attempt to
supplant malloc()/realloc()/free() with its own functions of the same
name.

The hardest part of the job when I port our version of the Bourne
shell to a new UNIX environment is untangling the shell's memory
manager, which attempts to replace the normal C library version,
often failing to meet the actual C implementation's constraints.
It was simply a design botch for the shell to have taken that approach.

scott@bbxsda.UUCP (Scott Amspoker) (09/21/89)

In article <11117@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>
>A program can wrap the system-provided malloc()/realloc()/free() with
>its own bookkeeping module, if desired, but strict standard
>conformance (or maximal portability) requires that it not attempt to
>supplant malloc()/realloc()/free() with its own functions of the same
>name.

We have done something similar to what the original poster was talking
about.  We have had our own routines that our software calls to do
malloc() and free().  These routines normally just pass on the arguments
to the real malloc() and free().  However, in a debugging situation
these routines will keep track of malloc'ed and free'ed areas to help
figure out what it going on if pointers are being trashed.  But, no,
we don't call them malloc() and free().  Of course, now we're being
told that we're not allowed to do our own pointer checking.

-- 
Scott Amspoker
Basis International, Albuquerque, NM
(505) 345-5232

marcus@illusion.UUCP (Marcus Hall) (09/22/89)

In article <1989Sep16.224730.9733@twwells.com> bill@twwells.com (T. William Wells) writes:
>I will judge compilers on compliance to the standard first, and
>quality of implementation second. Speed is an important consideration
>and, since *I* won't do stupid things like look at pointers when I'm
>not supposed to, go ahead and trash freed pointers. Now, I'll admit
>that I'd like a compiler option that turns off this optimization, but
>I won't insist.

Re-use of registers and/or memory locations is something that the compiler
should be capable of determining without resorting to knowing that a free'd
pointer shouldn't be used anymore.  If your program doesn't use the pointer
after calling free(), the compiler should be able to determine that the
register can be re-used.  If you do use it again, there may be a problem on
some machines; certainly referencing what it points to could cause problems,
but it seems rather out of place for the compiler to just assume that you
won't use it again -- especially if the compiler could determine whether or
not your code actually does.

There are some cases where it may be desirable for the compiler to make
assumptions about the actions of recognized library calls (for instance, if
a routine ends with a call to exit(), what is the point of producing code
to do stack cleanup and subroutine return?  I would have preferred it if the
compiler were to recognize something like __exit and for exit() to be #defined
to __exit() or some such, but this apparently isn't required.

Anyhow, this case shouldn't really be anything special.  If the last use of
a veriable is in a call to printf(), I wouldn't be upset if the compiler
re-used the register or memory location for some other variable.  It would
still be correct code and other than efficiency (or using the 2nd variable
without initializing it) the optimization should be invisible.  This does
not matter whether the function is printf(), free(), or anything else.

marcus hall

richard@aiai.ed.ac.uk (Richard Tobin) (09/27/89)

In article <11117@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>In article <902@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes:

>>This is a real pain for programs (like interpreters for other languages)
>>that need to keep track of just what memory is in use.

>Because a strictly conforming program cannot take cognizance of
>implementation-specific details, they needn't be of concern.

Many types of program can't be strictly conforming, but are nonetheless
useful.

The example I had in mind was the facility provided by many interactive
languages for the dynamic loading of C (and other) code.  Any reasonable
Lisp or Prolog system will provide this (examples of its use are: re-using
existing code written in another language, access to system calls and so
forth, and critical procedures that cannot be written sufficiently 
efficiently in the host language).

The code loaded in will often want to allocate memory, and the host
language may need to know about this so that it can (for example) garbage
collect safely.  The user may not have access to the source of the loaded
code (it might be a graphics library, for example), but if it only takes
advantage of the advertised features of standard routines (such as malloc)
then the host language can simulate them.

Now, you may regard this as a hack, but it's certainly a useful hack,
and it would be nice if there was a reliable way of doing it.

-- Richard
-- 
Richard Tobin,                       JANET: R.Tobin@uk.ac.ed             
AI Applications Institute,           ARPA:  R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk
Edinburgh University.                UUCP:  ...!ukc!ed.ac.uk!R.Tobin

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/28/89)

In article <946@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes:
>Now, you may regard this as a hack, but it's certainly a useful hack,
>and it would be nice if there was a reliable way of doing it.

It would be nice if nobody in the world were starving,
but that too is beyond the scope of the C Standard.

Your hack will work in some environments and not in others;
that's just the way it is.