2017-04-25 14 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; 

I는 다음과 같이 다시 쓸 경우

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는 UCC를 피하기 위해 코드를 다시 작성하는 방법이 아니라 GCC의 문제에 대해 질문합니다. – yugr

답변

2

는 기본적으로이 GCC의 -Wstrict-aliasing 기계의 버그입니다. 거짓 경고를 내고 실제 별칭 위반을 놓치는 것으로 알려져 있습니다 (개발자의 this comment 참조).

두 경우 모두 문제가 있습니다. 관계가없는 구조체를 캐스팅하면 앨리어싱 규칙이 위반되고 GCC에서 예상치 못한 코드가 발생할 수 있습니다.