2017-04-25 3 views
2

Dans la fonctionRésolution Avertissement GCC: "pointeur punned de type déréférencement brisera des règles strictes-aliasing" par pointeur temporaire

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

Je reçois l'avertissement: "pointeur de type punned déréférencement brisera stricte-aliasing règles [-Wstrict-aliasing] "sur la ligne suivante:

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

Si je réécris comme ceci:

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

Je ne reçois aucun avertissement. Pourquoi? Le problème est toujours là mais gcc ne peut pas le voir?

est ici les struct impliqués:

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; 
+3

Oui, le problème est toujours là, mais il semble que GCC perd la trace lorsque vous utilisez une variable intermédiaire. Votre code a un comportement indéfini et peut se bloquer dans diverses circonstances, ou peut-être pas; Cela dépend aussi de la configuration de bitfields. En outre, l'alignement de 'receive_mem' doit être vérifié - si les membres uint16_t sont mal alignés, cela peut provoquer des plantages –

+0

Je recommande d'utiliser' memcpy', comme dans cette réponse: http://stackoverflow.com/q/17789928 Vous pouvez voir que sous n'importe quel niveau d'optimisation, le compilateur est capable de le comprendre comme type-punning et omettre la copie de la mémoire réelle. https://godbolt.org/g/r6VoO0 – ephemient

+0

@AnttiHaapala S'il vous plaît noter que OP pose des problèmes sur GCC, pas comment réécrire le code pour éviter UB. – yugr

Répondre

2

En gros, cela est un bug dans les machines de GCC -Wstrict-aliasing. Il est connu à la fois de produire de faux avertissements et de manquer des violations d'alias réelles (voir this comment de développeurs).

Le problème est là dans les deux cas, la diffusion de structures non liées viole les règles d'aliasing et va probablement amener GCC à produire du code inattendu.