2017-04-25 7 views
2

によって「間接参照型punnedポインタが厳格なエイリアシング規則を破るだろう」解決GCC警告:機能では、一時的なポインタ

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

私は警告を受ける:「逆参照型punnedポインタが厳しいエイリアシングを中断しますルール次の行の[-Wstrictエイリアシング] ":

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

私はこのように書き換える場合:

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

私は警告を受けません。どうして?問題はまだありますが、gccはそれを見ることができませんか?ここで

は関与構造体です:

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

はい、問題はまだありますが、中間変数を使用するとGCCがトラックを失うようです。コードには未定義の動作があり、さまざまな状況でクラッシュする可能性があります。また、ビットフィールドのレイアウトも非常に多くの実装が定義されています。また、 'receive_mem'のアライメントをチェックする必要があります - もしuint16_tのメンバーが整列していないとクラッシュする可能性があります –

+0

この回答のように' memcpy'を使うことをお勧めします:http://stackoverflow.com/q/17789928どのような最適化レベルでも、コンパイラはそれを型打ちとして理解し、実際のメモリコピーを省略することができます。 https://godbolt.org/g/r6VoO0 – ephemient

+0

@AnttiHaapala OPがGCCの問題について質問していますが、UBを避けるためにコードを書き直す方法ではないことに注意してください。 – yugr

答えて

2

は、基本的にこれはGCCの-Wstrict-aliasing機械のバグです。誤った警告と実際のエイリアス違反の両方が発生することが知られています(開発者のthis commentを参照)。

どちらの場合も、関係のない構造体をキャストするとエイリアスルールに違反し、GCCが予期しないコードを生成する可能性があるという問題があります。

関連する問題