Topic: Casting pointers to integers and back
Author: harrison@sp1.csrd.uiuc.edu (Luddy Harrison)
Date: Thu, 13 May 93 15:36:05 GMT Raw View
I write:
> ...the important point is that the [pointer-to-int] cast must
> produce the same value every time it is performed.
ellis@parc.xerox.com (John Ellis) writes:
>I don't think the ANSI C standard requires this constancy. Section
>3.3.4 says:
[ omitted ]
In the style of cast you have in mind, the int that results is not
useful as an integer, because its value is not constant (that is, doing
the cast again may yield a different integer); nor is it
useful as a pointer, because it is not guaranteed to point to anything
when it is cast back to a pointer. What could it possibly be used for?
In this case, would it not make more sense to simply forbid the cast
from pointer to int altogether?
I can't find anything in the C standard that forbids the implementation
that you have in mind, but I will point out that the footnote to section
3.3.4 (footnote 42) says "The mapping function for converting a pointer
to an integer ...". The operative word here is function; a one-to-many-
valued cast is not a function. (:
Perhaps we can at least agree that such an implementation will break
virtually every program that contains a cast from pointer to int.
Author: ellis@parc.xerox.com (John Ellis)
Date: Fri, 14 May 1993 16:45:02 GMT Raw View
harrison@sp1.csrd.uiuc.edu (Luddy Harrison) writes:
In this case, would it not make more sense to simply forbid the
cast from pointer to int altogether?
Yes, the safety rules for any reasonably efficient GC proposal would
have to forbid the cast (as our proposal does).
However, if the standard defined such casts as "undefined" or
"implementation dependent", then the safety rules for GC become a
little simpler. Currently, the GC-safety rules say, "Don't use the
following implementation-dependent or undefined features of C++; and
don't cast pointers to integers and back."
It would be more succint if one could say that any strictly conforming
C++ program is also GC-safe. (Of course, guidelines to programmers
would still have to emphasize that certain implementation-dependent
features couldn't be used reliably.)
Author: ellis@parc.xerox.com (John Ellis)
Date: Wed, 12 May 1993 20:14:32 GMT Raw View
There is a difference between ANSI C and the ARM that is not listed in
the ARM section 18.2:
The ARM specifically allows a pointer to be cast to an integer of
sufficient size and back again, yielding the same pointer value
(section 5.4).
The ANSI C standard states that casting a pointer to an integer and back
will not necessarily yield the same pointer value (3.3.4, Rationale 3.3.4).
Has there been committee discussion about this difference? If not,
should there be?
If C++ followed the ANSI C behavior, then C++ would not require any
additional rules for correct use of garbage collection. With the
current ARM definition, garbage collection requires such casts to be
prohibited.
Author: harrison@sp1.csrd.uiuc.edu (Luddy Harrison)
Date: Wed, 12 May 93 20:50:47 GMT Raw View
ellis@parc.xerox.com (John Ellis) writes:
>There is a difference between ANSI C and the ARM that is not listed in
>the ARM section 18.2:
> The ARM specifically allows a pointer to be cast to an integer of
> sufficient size and back again, yielding the same pointer value
> The ANSI C standard states that casting a pointer to an integer and back
> will not necessarily yield the same pointer value (3.3.4, Rationale 3.3.4).
>If C++ followed the ANSI C behavior, then C++ would not require any
>additional rules for correct use of garbage collection. With the
>current ARM definition, garbage collection requires such casts to be
>prohibited.
Such a rule might be sufficient to guarantee the correctness of a GC
that provides automatic release of data, but in the case of a copying
GC, I think that the issue is a bit more complicated than that. A program
that contains this code:
Foo* p;
...
int x = Hash((unsigned long)p);
...
int y = Hash((unsigned long)p);
assert(x == y);
will work correctly under C and C++ in the absense of GC. It will be
broken by a GC that moves the data pointed to by p. Note that there
is no cast in the direction (unsigned long) -> Foo*, only unidirectional
casts from Foo* -> (unsigned long). This unidirectional cast may discard
bits from p, it makes no difference; the important point is that the
cast must produce the same value every time it is performed.
Author: ellis@parc.xerox.com (John Ellis)
Date: Wed, 12 May 1993 22:15:59 GMT Raw View
harrison@sp1.csrd.uiuc.edu (Luddy Harrison) writes:
...the important point is that the [pointer-to-int] cast must
produce the same value every time it is performed.
I don't think the ANSI C standard requires this constancy. Section
3.3.4 says:
A pointer may be converted to an integral type. The size of
integer required and the result are implementation-defined.
with a footnote:
The mapping mapping functions for converting a pointer to an
integer ... are intended to be consistent with the addressing
structure of the execution environment.
In the Rationale, section 3.3.4 it says:
Nothing portable can be said about casting integers to pointers,
or vice versa, since the two are now incommensurate.
I would conclude from this that a conforming program can't rely on the
constancy of casting a particular pointer. Nothing in the standard
appears to prevent the execution environment from providing an
addressing structure in which objects are relocated.
Such a rule might be sufficient to guarantee the correctness of a
GC that provides automatic release of data, but in the case of a
copying GC, I think that the issue is a bit more complicated than
that.
I agree. The proposal for C++ GC written by Detlefs and myself
addresses this issue in detail.