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

4

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?

Hematology answered 12/8, 2010 at 5:9 Comment(0)
S
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
Sinker answered 20/8, 2013 at 17:59 Comment(0)
D
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.

Devinna answered 12/8, 2010 at 7:9 Comment(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.Ballocks
N
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.

Nurmi answered 12/8, 2010 at 5:54 Comment(3)
@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.Devinna
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.Nurmi
'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.Gaucherie
B
-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.

Ballocks answered 12/8, 2010 at 5:29 Comment(3)
Sockets are not part of a compiler implementation but part of the operating system.Devinna
Where the programmer has "#include <something.h>", 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.Ballocks
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.Gaucherie

© 2022 - 2024 — McMap. All rights reserved.