11

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?

GManNickG
  • 494,350
  • 52
  • 494
  • 543
Nantucket
  • 1,647
  • 3
  • 14
  • 25

4 Answers4

6

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
tloach
  • 8,009
  • 1
  • 33
  • 44
2

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.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • 1
    If gcc doesn't give you the same warning when you use *act, either you didn't enable the same warnings that the original poster did, or you found a bug in gcc. – Windows programmer Aug 12 '10 at 08:14
1

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.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 1
    @R. first I don't think that it is stated that `sa_family/sin_family` is a common initial element. They must be present both, with identical values. Then the access as the OP gave it *is* a violation of aliasing rules, basically he is doing `((struct sockaddr_in *)addr)->sin_addr` which is a common idiom to do such things. – Jens Gustedt Aug 12 '10 at 07:16
  • Casting a pointer and then dereferencing it is, by itself, **never** a violation of aliasing rules. Only if you also dereferenced it though the original type can aliasing rules have been violated. Regardless of whether POSIX guarantees that `*_family` is a common initial element, in practice it **is**, and gcc, having the structure definition, knows this. So my claim about no aliasing rules having been violated is correct. – R.. GitHub STOP HELPING ICE Aug 12 '10 at 07:47
  • 'They must be present both, with identical values' doesn't mean anything. You're talking about the same piece of memory. Of course the values are the same. – user207421 Dec 07 '10 at 02:00
-2

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.

Windows programmer
  • 7,871
  • 1
  • 22
  • 23
  • 1
    Sockets are not part of a compiler implementation but part of the operating system. – Jens Gustedt Aug 12 '10 at 07:15
  • Where the programmer has "#include ", either that header file something.h is part of a C or C++ implementation, or else the programmer is lucky that things work as well as they do and the programmer has to solve it theirself. – Windows programmer Aug 12 '10 at 08:09
  • 1
    That's only true for #include files that are part of the language, e.g. stdlib.h. Socket include files are part of a sockets SDK, not the compiler. – user207421 Dec 07 '10 at 02:02