In the source code of the ping from freebsd
, I noticed this when the code is dealing with control data that contain timestamp
from SO_TIMESTAMP
socket option:
Here' example:
#ifdef SO_TIMESTAMPif (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_TIMESTAMP &&
cmsg->cmsg_len == CMSG_LEN(sizeof *tv)) {
/* Copy to avoid alignment problems: */
memcpy(&now, CMSG_DATA(cmsg), sizeof(now));
tv = &now;
}
#endif
What are the alignment problems author had in mind and why isn't it sufficient to just save a pointer to CMSG_DATA(cmsg)
?
Is it important I copy the ancillary data myself when dealing with the same situation?
Full source code is here:(See docs)
cmsg
is a struct cmsghdr
, which is a variable length structure that consists of a few fields at the beginning, followed by arbitrary bytes starting at cmsg_data
. Since structure of the arbitrary bytes is not known at compile time, the place where the bytes start might not provide for the fields in the structure to be properly aligned. (See http://en.wikipedia.org/wiki/Data_structure_alignment for some background information).
So what is happening here is that the expression in the if
statement is checking what type of data the arbitrary bytes actually are, at runtime. If the level, type, and length indicate that the data is a struct timeval
, then the bytes are copied (via the CMSG_DATA
macro) into a properly aligned structure on the stack.