Strict aliasing and overlay inheritance

前端 未结 2 1099
攒了一身酷
攒了一身酷 2020-12-17 21:59

Consider this code example:

#include 

typedef struct A A;

struct A {
   int x;
   int y;
};

typedef struct B B;

struct B {
   int x;
   in         


        
相关标签:
2条回答
  • 2020-12-17 22:10

    When C89 was written, it would have been impractical for a compiler to uphold the Common Initial Sequence guarantees for unions without also upholding them for struct pointers. By contrast, specifying the CIS guarantees for struct pointers would not imply that unions would exhibit similar behavior if their address was not taken. Given that the CIS guarantees have been applicable to struct pointers since January 1974--even before the union keyword was added to the language--and a lot of code had for years relied upon such behavior in circumstances which could not plausibly involve objects of union type, and that the authors of the C89 were more interested in making the Standard concise than in making it "language-lawyer-proof", I would suggest that C89's specification of CIS rule in terms of unions rather than struct pointers was almost certainly motivated by a desire to avoid redundancy, rather than a desire to allow compilers the freedom to go out of their way to violate 15+ years of precedent in applying CIS guarantees to structure pointers.

    The authors of C99 recognized that in some cases applying the CIS rule to structure pointers might impair what would otherwise be useful optimization, and specified that if a pointer of one structure type is used to inspect a CIS of member of another, the CIS guarantee won't hold unless a definition of a complete union type containing both structures is in scope. Thus, for your example to be compatible with C99, it would need to contain a definition of a union type containing both of your structures. This rule appears to have been motivated by a desire to allow compilers to limit application of the CIS to cases where they would have reason to expect that two types might be used in related fashion, and to allow code to indicate that types are related without having to add a new language construct for that purpose.

    The authors of gcc seem to think that because it would be unusual for a code to receive a pointer to a member of a union and then want to access another member of a union, the mere visibility of a complete union type definition should not be sufficient to force a compiler to uphold CIS guarantees, even though most uses of the CIS had always revolved around structure pointers rather than unions. Consequently, the authors of gcc refuse to support constructs like yours even in cases where the C99 Standard would require it.

    0 讨论(0)
  • 2020-12-17 22:11

    The line with *ap = is a strict aliasing violation: an object of type B is written using an lvalue expression of type A.

    Supposing that line was not present, and we moved onto ap->x = 10; ap->y = 20;. In this case an lvalue of type int is used to write objects of type int.

    There is disagreement about whether this is a strict aliasing violation or not. I think that the letter of the Standard says that it is not, but others (including gcc and clang developers) consider ap->x as implying that *ap was accessed. Most agree that the standard's definition of strict aliasing is too vague and needs improvement.

    Sample code using your struct definitions:

    void f(A* ap, B* bp)
    {
      ap->x = 213;
      ++bp->x;
      ap->x = 213;
      ++bp->x;
    }
    
    int main()
    {
       B b = { 0 };
       f( (A *)&b, &b );
       printf("%d\n", b.x);
    }
    

    For me this outputs 214 at -O2, and 2 at -O3 , with gcc. The generated assembly on godbolt for gcc 6.3 was:

    f:
        movl    (%rsi), %eax
        movl    $213, (%rdi)
        addl    $2, %eax
        movl    %eax, (%rsi)
        ret
    

    which shows that the compiler has rearranged the function to:

    int temp = bp->x + 2;
    ap->x = 213;
    bp->x = temp;
    

    and therefore the compiler must be considering that ap->x may not alias bp->x.

    0 讨论(0)
提交回复
热议问题