Search code examples
cpointersgccstrict-aliasingtype-punning

Solving GCC Warning: "dereferencing type-punned pointer will break strict-aliasing rules" by temporary pointer


In the function

size_t csps_socket_read(csps_socket_t *s, csps_packet_wrapper_t *packet, size_t sz)

I get the warning: "dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]" on the following line:

packet_size = ((csps_packet_full_header_t *)s->receive_mem)->size + header_size;

If I rewrite like this:

csps_packet_full_header_t *packet_full_header = (csps_packet_full_header_t *)s->receive_mem;
packet_size = packet_full_header->size + header_size;

I get no warning. Why? Is the problem still there but gcc can't see it?

Here's the structs involved:

typedef struct csps_socket_t_
{
    void*       fp;
    bool        open;
    uint8_t     receive_mem[CSPS_SOCKET_MEM];
    uint32_t    receive_index;
} csps_socket_t;

typedef struct ATTR_PACKED csps_packet_full_header_t_
{
    uint8_t version:4;
    uint8_t pclass:4;
    uint8_t ch:1;
    uint8_t reserved:7;
    uint16_t size;
    uint16_t sequence;
    uint16_t checksum;
    uint8_t src[8];
    uint8_t dst[8];
} csps_packet_full_header_t;

Solution

  • Basically this is a bug in GCC's -Wstrict-aliasing machinery. It's known to both produce false warnings and miss real aliasing violations (see this comment from developers).

    The problem is there in both cases, casting unrelated structs will violate aliasing rules and will likely cause GCC to produce unexpected code.