i.e. GCC doesn't properly analyze the code that it optimizes, so it
generates the wrong optimizations. GCC has a history of doing this...
I'm not expert enough in the C99 standard to judge whether the comments
at the above URL are correct or not; I suspect it's a matter of some
controversy, and will back slowly away now... ;o)
I think your comments about the underlying cause are correct.
Ulrich's comments about Posix are interesting:
The invalid casts are forbidden by ISO C. POSIX
does not and cannot guarantee anything about this type of use of
sockaddr_storage.
To quote the Opengroup page:
http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/socket.h.html
...
The <sys/socket.h> header shall define the sockaddr_storage structure.
This structure shall be:
* Large enough to accommodate all supported protocol-specific
address structures
* Aligned at an appropriate boundary so that pointers to it can be
cast as pointers to protocol-specific address structures and used to
access the fields of those structures without alignment problems
...
i.e. the code in FreeRADIUS is correct.
For what it's worth my reading of the above statements is different
than yours. I read the above as sockaddr_storage provides a type whose
size is sufficient to hold all sockaddr types while respecting the
alignment requirement in any given sockaddr type. The discussion of
pointer casting fails to make explicit such casting must still conform
to the rules of C99. I do not read the second paragraph as meaning
pointer aliasing shall be supported, something outside that scope of
that document.
It uses sockaddr_stoage as a
generic container for protocol-specific address structures. It casts a
pointer to sockaddr_storage to a pointer to protocol-specific address
structures. The recommendation to use a union to hold both
sockaddr_storage && sockaddr_in is... interesting. If you have to do
that, WTF is the use of sockaddr_storage?
Looking on the net, I also found a fair amount of code using
sockaddr_storage in the recommended Posix way. It appears that
FreeRADIUS is OK, and just got hit by a GCC bug.
i.e. for ANY code like this:
foo = (type_t *) bar;
switch (x) {
case 1:
foo->a = 1;
break;
...
}
function(&bar);
GCC will "optimize away" the line doing "foo->a = 1;". Nice.
Alan DeKok.
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
I have created a patch for packet.c which uses a union (the patch is
attached). I built freeradius 2.0.4 with the patch and -O2 optimization
and the random port problem seems to have been resolved. Note, I have
not looked though all the source code to see if there are other code
constructs which may also require a fix. I expect I'll push a 2.0.4
version of FreeRADIUS with full -O2 optimization into the F-9
updates-testing stream with the patch. However, I'll wait a bit to see
if others chime in with any other known problem areas first which
should be folded into any such patch.