❦ 14 mai 2016 15:20 +0200, Cyril Bonté <cyril.bo...@free.fr> : >>> 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