Dereferencing pointer does break strict anti-aliasing rules using Berkeley sockets

10.6k Views Asked by At

I've got code that looks something like this, where addr is a sockaddr*:

struct sockaddr_in *sin = (struct sockaddr_in *) addr;
const char *IP=inet_ntoa(sin -> sin_addr);

I believe this is very typical code for using Berkeley sockets.

However, when I compile this, I'm getting the following warning:
dereferencing pointer 'sin' does break strict anti-aliasing rules

Searching online, I find some discussion of the fact that the way I'm doing things is pretty typical, but this compiler warning also is pretty real and not a good thing.

What's the proper way to redo this code to fix the warning, and not just silence it?

4

There are 4 best solutions below

0
On

I had the same issue - it looks like a bug in gcc.

I was able to get around it by using

(*sin).sin_addr

instead of

sin->sin_addr
3
On

If your header file and your compiler are both parts of the same C or C++ implementation, complain to your vendor and ask them to put a suitable #pragma in their header file to silence their compiler. As implementor, they're allowed to play games like that, as long as they provide a conforming implementation.

If your header file and your compiler came from two separate C or C++ implementations, you're lucky that things work as well as they do, and you have to solve it yourself.

3
On

Depending on how you've used struct sockaddr, I think either your code is broken, or gcc is broken. struct sockaddr and struct sockaddr_in have a common initial element (sa_family/sin_family) so it does not violate aliasing rules if you have accessed only this element through both pointers; doing so is permitted by C99. Moreover, struct sockaddr has no other elements you're allowed to access. It's largely an opaque type for primitive socket address polymorphism. If you have been poking around at implementation-specific internals in struct sockaddr, or worse yet, if you declared a struct sockaddr object rather than just a pointer or performed copying between such objects, your code is broken. If you didn't, and gcc is giving a warning claiming you've broken aliasing rules, then gcc's warning generation is broken. I surely wouldn't be surprised if it's the latter.

1
On

Yes, this is a know problem with gcc and sockets. The problem basically seems to be that the way this ip[46] stuff is designed is incompatible with the assumptions that the gcc people think they can deduce about aliasing of pointers.

I usually get away with this by first taking a pointer on the struct

struct in_addr* act = &(sin->sin_addr);

and then using *act.