freakish freakish - 2 months ago 13
C++ Question

Why reinterpret_cast fails while memcpy works?

I'm writing some socket code and based on some params I'm using either IPv4 or IPv6. For that I have a code like this:

struct sockaddr final_addr;
...
struct sockaddr_in6 addr6;
...
memcpy(&final_addr, &addr6, size);
...
bind(fd, &final_addr, size);


This works fine. However if I do (which was my initial idea)

struct sockaddr final_addr;
...
struct sockaddr_in6 addr6;
...
final_addr = *reinterpret_cast<struct sockaddr*>(&addr6);
...
bind(fd, &final_addr, size);


then it fails on
bind
with
Cannot assign requested address
error.

Note that this incorrect code works fine if I switch to IPv4's
sockaddr_in
.

What's going on here? Why can't I just reinterpret
sockaddr_in6
as
sockaddr
?

AnT AnT
Answer

If in the first version of the code size is sizeof(addr6) (as you stated in the comments), then the first version of the code uses memcpy to copy sizeof(struct sockaddr_in6) bytes of data.

The second version of the code uses regular struct sockaddr assignment to copy only sizeof(struct sockaddr) bytes.

sizeof(struct sockaddr) is smaller than sizeof(struct sockaddr_in6), which makes these two code samples different.

Note that in the first version the recipient object in that memcpy is of struct sockaddr type, i.e. it is smaller than the number of bytes copied. Memory overrun occurs, which clobbers some other data stored in adjacent memory locations. The code "works" only by accident. I.e. if this bit "works", then some other piece of code (the one that relies on the now-clobbered data) is likely to fail.