I'm using Beej's Guide to Networking and came across an aliasing issue. He proposes a function to return either the IPv4 or IPv6 address of a particular struct:
1 void *get_in_addr( struct sockaddr *sa )
2 {
3 if (sa->sa_family == AF_INET)
4 return &(((struct sockaddr_in*)sa)->sin_addr);
5 else
6 return &(((struct sockaddr_in6*)sa)->sin6_addr);
7 }
This causes GCC to spit out a strict-aliasing error for sa on line 3. As I understand it, it is because I call this function like so:
struct sockaddr_storage their_addr;
...
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
connection_name,
sizeof connection_name);
I'm guessing the aliasing has to do with the fact that the their_addr
variable is of type sockaddr_storage
and another pointer of a differing type points to the same memory.
Is the best way to get around this sticking sockaddr_storage
, sockaddr_in
, and sockaddr_in6
into a union? It seems like this should be well worn territory in networking, I just can't find any good examples with best practices.
Also, if anyone can explain exactly where the aliasing issue takes place, I'd much appreciate it.
I tend to do this to get GCC do the right thing with type-punning, which is explicitly allowed with unions:
/*! Multi-family socket end-point address. */
typedef union address
{
struct sockaddr sa;
struct sockaddr_in sa_in;
struct sockaddr_in6 sa_in6;
struct sockaddr_storage sa_stor;
}
address_t;
I tend to do this to get GCC do the right thing with type-punning, which is explicitly allowed with unions
I am pretty sure this (mis)use of union will not work (or only by accident) with GCC:
short type_pun2 (int i, int *pi, short *ps) { *pi = i; return *ps; } union U { int i; short s; }; short type_pun (int i) { U u; return type_pun2 (i, &u.i, &u.s); }
The correct way to do that is with memcpy
, not union
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With