cast from sockaddr * to sockaddr_in * increases required alignment

后端 未结 3 1742
情书的邮戳
情书的邮戳 2021-01-05 13:53

The compiler produces this warning when I\'m working with some code which looks like -

....

for(p = res; p != NULL; p = p->ai_next) {
    void *addr;
           


        
3条回答
  •  难免孤独
    2021-01-05 14:32

    TLDR: This warning doesn't indicate an error in your code, but you can avoid it by using a poper c++ reinterpret_cast (thanks to @Kurt Stutsman).


    Explanation:

    Reason for the warning:

    • sockaddr consists of a unsigned short (usually 16 bit) and a char array, so its alignment requirement is 2.
    • sockaddr_in contains (among other things) a struct in_addr which has an alignment requirement of 4 which in turn means sockaddr_in also must be aligned to a 4 Byte boundary.

    For that reason, casting an arbitrary sockaddr* to an sockaddr_in* changes the alignment requirement, and accessing the object via the new pointer would even violate aliasing rules and result in undefined behavior.

    Why you can ignore it:

    In your case, the object, p->ai_addr is pointing to, most likely is a sockaddr_in or sockaddr_in6 object anyway (as determined by checking ai_family) and so the operation is safe. However you compiler doesn't know that and produces a warning.

    It is essentially the same thing as using a static_cast to cast a pointer to a base class to a pointer to a derived class - it is unsafe in the general case, but if you know the correct dynamic type extrinsically, it is well defined.

    Solution:
    I don't know a clean way around this (other than suppress the warning), which is not unusual with warnings enabled by -Weverything . You could copy the object pointed to by p->ai_addr byte by byte to an object of the appropriate type, but then you could (most likely) no longer use addr the same way as before, as it would now point to a different (e.g. local) variable.
    -Weverything isn't something I would use for my usual builds anyway, because it adds far too much noise, but if you want to keep it, @Kurt Stutsman mentioned a good solution in the comments:

    clang++ (g++ doesn't emit a warning in any case) doesn't emit a warning, if you use a reinterpret_cast instead of the c style cast (which you shouldn't use anyway), although both have (in this case) exactly the same functionality. Maybe because reinterpret_cast explicitly tells the compiler: "Trust me, I know, what I'm doing" .


    On a side Note: In c++ code you don't need the struct keywords.

提交回复
热议问题