Is gcc's __attribute__((packed)) / #pragma pack unsafe?

前端 未结 5 1259
广开言路
广开言路 2020-11-22 03:48

In C, the compiler will lay out members of a struct in the order in which they\'re declared, with possible padding bytes inserted between members, or after the last member,

5条回答
  •  青春惊慌失措
    2020-11-22 04:39

    As ams said above, don't take a pointer to a member of a struct that's packed. This is simply playing with fire. When you say __attribute__((__packed__)) or #pragma pack(1), what you're really saying is "Hey gcc, I really know what I'm doing." When it turns out that you do not, you can't rightly blame the compiler.

    Perhaps we can blame the compiler for it's complacency though. While gcc does have a -Wcast-align option, it isn't enabled by default nor with -Wall or -Wextra. This is apparently due to gcc developers considering this type of code to be a brain-dead "abomination" unworthy of addressing -- understandable disdain, but it doesn't help when an inexperienced programmer bumbles into it.

    Consider the following:

    struct  __attribute__((__packed__)) my_struct {
        char c;
        int i;
    };
    
    struct my_struct a = {'a', 123};
    struct my_struct *b = &a;
    int c = a.i;
    int d = b->i;
    int *e __attribute__((aligned(1))) = &a.i;
    int *f = &a.i;
    

    Here, the type of a is a packed struct (as defined above). Similarly, b is a pointer to a packed struct. The type of of the expression a.i is (basically) an int l-value with 1 byte alignment. c and d are both normal ints. When reading a.i, the compiler generates code for unaligned access. When you read b->i, b's type still knows it's packed, so no problem their either. e is a pointer to a one-byte-aligned int, so the compiler knows how to dereference that correctly as well. But when you make the assignment f = &a.i, you are storing the value of an unaligned int pointer in an aligned int pointer variable -- that's where you went wrong. And I agree, gcc should have this warning enabled by default (not even in -Wall or -Wextra).

提交回复
热议问题