❦ 14 mai 2016 15:20 +0200, Cyril Bonté <[email protected]> :
>>> What is the most important is to report this to the gcc maintainers so that
>>> they can fix the bug. The fix will naturally flow into the distros.
>>>
>>
>> I understand this and of course I could try to fill a bug on their side but
>> the gcc stuff is a bit out of my league.
>
> After spending some time on this, I'm now able to produce a minimal
> test case.
>
> $ gcc-6 -O2 -o debug debug.c && ./debug
> 0
> => here we have an issue, as it shouldn't be 0
>
> $ gcc-6 -O2 -DDEBUG -o debug debug.c && ./debug
> 7f000001
> 7f000001
> => Suddenly, everything works
>
> And now, what happens with this debug code when -fno-tree-sra is used ?
> $ gcc-6 -O2 -fno-tree-sra -DDEBUG -o debug debug.c && ./debug
> 7f000001
> 0
> => It still doesn't work :-( So, disabling "tree-sra" doesn't
> guarantee the right behaviour.
>
> I also attach a debug2.c example, which is also disturbing. It is the
> same code, but adds a local variable. Depending on the code order,
> strange things happen (looks like a memory alignment issue).
> For example :
> $ gcc-6 -O2 -o debug2 debug2.c && ./debug2
> 0
> fd7f0000
>
> Note : my tests were made on a Debian SID with the gcc-6 package.
I think this is an aliasing problem. You cannot have two incompatible
variables pointing at the same memory spot. It seems that now
sockaddr_storage and sockaddr_in are not compatible anymore.
#v+
struct sockaddr_storage
{
__SOCKADDR_COMMON (ss_); /* Address family, etc. */
__ss_aligntype __ss_align; /* Force desired alignment. */
char __ss_padding[_SS_PADSIZE];
};
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_);
in_port_t sin_port; /* Port number. */
struct in_addr sin_addr; /* Internet address. */
/* Pad to size of `struct sockaddr'. */
unsigned char sin_zero[sizeof (struct sockaddr) -
__SOCKADDR_COMMON_SIZE -
sizeof (in_port_t) -
sizeof (struct in_addr)];
};
#v-
If I introduce this type:
#v+
struct sockaddr_storage_universal {
union {
struct sockaddr_storage sas;
struct sockaddr_in sai;
struct sockaddr_in6 sai6;
};
};
#v-
This works when used in place of "struct sockaddr_storage". I see the
glibc is using an union too instead of struct sockaddr or struct
sockaddr_storage. man 7 socket still says to use struct
sockaddr_storage.
Searching a bit, there is this old question on StackOverflow:
http://stackoverflow.com/questions/1429645/how-to-cast-sockaddr-storage-and-avoid-breaking-strict-aliasing-rules
--
I think we are in Rats' Alley where the dead men lost their bones.
-- T.S. Eliot