This is a discussion on RE: OpenSSL breaks with gcc 4.2 - Openssl ; > An object may be the type of its last cast -- but it also can't > exactly lose the benefit/cost of being cast to a pointer to an > undefined type. As soon as you undefine the type of ...
> An object may be the type of its last cast -- but it also can't
> exactly lose the benefit/cost of being cast to a pointer to an
> undefined type. As soon as you undefine the type of a pointer, it
> loses the remnant of ever having had the initial type in the first
Right, but that doesn't help you. For example:
double *d=3D(double *)(void *)&j;
This can output 2. Even though '&j' lost all intness by the cast to =
'void *', it got 100% doubleness by the cast to 'double *'. The compiler =
can still assume that '*d' will not affect the value of 'j' because 'd' =
is a pointer to a type that is incompatible with 'j's type.
The rule still stands -- a modification through a pointer to one type =
can be assumed not to change the value of a variable of an incompatible =
This is still what OpenSSL does when it passes an 'X509 **' as a 'char =
> In K&R C, you couldn't cast to void *, that was first introduced in
> C89. You had to cast to char *, and then you could cast to some other
> type in order to make your array indexes jump sizeof(type),
> essentially (on 8-bit byte machines) referencing
The cast to 'char *' made things safe. However, once you cast it away =
from 'char *', it became dangerous again. There was no remnant of the =
'char *' cast. Yes, while it was a 'char *', it could alias anything, =
but as soon as you cast it to something else, it can no longer legally =
alias an incompatible type.
However, it should be safe to pass a 'char *' to a function that takes a =
'char *', and cast that parameter back to its real value in the =
function. For example, this should be legal:
int inc(int is_double, char *pointer)
double *p=3D(double *) pointer;
int *p=3D(int *) pointer;
int i=3Dto_int(1, (char *) &j);
That is because you are passing the function a compatible type, the =
compiler must assume a 'char *' might alias anything, and you are only =
dereferencing the pointer as a compatible type.
> Actually, what's broken is not allowing a large class of useful=20
> optimizations for the occasional code that chooses to invoke=20
> undefined behavior. That said, I do exactly what you suggest.=20
> I've had too much old code break horribly and subtly to find the=20
> optimizations worth the risk. So my 'official' position is not=20
> the same as my personal position.
> 'occasional'? I've never examined any substantial program in C that
> doesn't invoke that -- even if just to be able to read data from disk
> into memory.
Many programs do aliasing correctly, following the rules that permit =
pointers to alias. However, I think it's a very fair point that nobody =
seems to totally understand what the rules *are*, which makes it hard to =
be sure you're following them.
> An object is the type of the last cast -- but if it's ever cast to
> void *, it must be treated as if it were never any type before that.
The problem is precisely that it loses its association with the type it =
first was! If it kept its association with the first type, there'd be no =
Look at this code again:
double *d=3D(double *)(void *)&j;
The *problem* is that '&j' has list its intness.
OpenSSL Project http://www.openssl.org
Development Mailing List email@example.com
Automated List Manager firstname.lastname@example.org