2016-08-30 1 views
1

다음 코드는 int64_t을 정의하는 플랫폼에 대한 표준을 합당하게 읽은 상태에서 100 % 정의 된 동작을 가져야하며 long long이 별칭으로 인식되는지 여부에 관계없이 long long의 크기와 표현이 같은 경우 호환.gcc 6.2의 저장소 재사용 (앨리어스) 버그입니까?

다음 몇 가지 스토리지 할당해야 test3에 대한

수정 코드 (GCC 6.2 - 64이 -std=c99 -x c -O2 사용) https://godbolt.org/g/75oLGx에서

#include <stdint.h> 
#include <string.h> 
#include <stdlib.h> 
#include <stdio.h> 

typedef long long T1; 
typedef int64_t T2; 
#define T1FMT "%lld" 
#define T1VALUE 1 
#define T2VALUE 2 

T1 blah3(void *p1, void *p2) 
{ 
    T1 *t1p, *t1p2; 
    T2 *t2p; 
    T1 temp; 

    t1p = p1; 
    t2p = p2; 
    *t1p = T1VALUE; // Write as T1 
    *t2p = T2VALUE; // Write as T2 
    temp = *t2p;  // Read as T2 
    t1p2 = (T1*)t2p; // Visible T2 to T1 pointer conversion 
    *t1p2 = temp;  // Write as T1 
    return *t1p;  // Read as T1 
} 

T1 test3(void) 
{ 
    void *p = malloc(sizeof (T1) + sizeof (T2)); 
    T1 result = blah3(p,p); 
    free(p); 
    return result; 
} 
int main(void) 
{ 
    T1 result = test3(); 
    printf("The result is " T1FMT "\n", result); 
    return 0;  
} 

참조 코드 :

  1. 가치와 long long 기록 1.
  2. 값이 2 인 int64_t을 작성하여 저장 장치의 유효 유형을 int64_t으로 설정합니다.
  3. ,
  4. 는 (여기서 2이어야 함), 상기 값은 A long long 저장하여 long long 2 개
  5. 세트 스토리지의 유효 형을 수득한다 int64_t 같은 스토리지 (유효 타입) 읽는다.
  6. 2.

godbolt 사이트에서 GCC 6.2 - 64을 수득한다 형 long long로 저장을 읽을 수 있지만, 2 산출하지 않는다; 대신에 그것은 1을 산출합니다. gcc가 어떤 유형의 조합을 찾지 못했습니다 이렇게. gcc가 t1p2에 대한 저장소가 효과가 없기 때문에 생략 될 수 있다고 결정하지만 저장소에 유효 유형을 int64_t에서 long long으로 변경하는 효과가 있음을 인식하지 못했습니다. 내가없는 결정이 별칭 호환되는 것으로 int64_tlong long을 인식 의심 고려하면서

, 나는 그것이 이전에 보유하고 있던 한 후 값 2를 개최 스토리지의 재사용을 인식하는 GCC의 실패를 정당화 표준에서 아무것도 볼 값 1. 아무 것도 쓰여진 타입이 아닌 다른 타입으로 읽혀지는 것은 없지만, gcc는 "ㅋ"로 전달 된 두 포인터가 별칭이 될 수 없다고 판단하고 있다고 생각합니다.

나는 아무것도 없거나 철저한 버그입니까?

답변

0

설명대로 코드가 엄격한 앨리어싱 규칙을 위반하지 않습니다. 실제로 T1T2은 유형이 다를 수 있습니다 (할당이 유형 불일치가 아니어도 됨). 크기가 같거나 다를 필요는 없습니다.

출력 1은 컴파일러 버그입니다. godbolt 사이트에서 gcc의 모든 버전에는 버그가있는 것 같지만 clang은 올바른 결과를 제공합니다.

그러나 로컬 설치 gcc 4.9.2 (x86_64-win32-seh-rev1)에서는 올바른 출력 2를 얻었습니다. gcc의 일부 빌드에만 문제가있는 것 같습니다.

+0

내가 알 수있는 한 버그의 주요 조건은 컴파일러가 스토어를 '* t1p2' (으)로 간주해야한다는 것입니다. gcc의 모든 설치가'int64_t'에 대해 동일한 정의를 사용하는지 여부는 알지 못합니다. 왜냐하면 그 유형이'long long'으로 지정된 플랫폼에서 여기에 표시된 코드는 여기에 표시된 것처럼 잘 작동하지만 T1이 'long'으로 변경되었습니다.만약 표준 컴파일러가 동일한 크기와 표현을 가진 타입 사이의 앨리어싱을 인식하지 못한다고 생각한다면, 그것을 인식하지 못하면 매우 어렵게 될 것입니다 ... – supercat

+0

... 정의 된 데이터 교환 동일한 데이터 형식에 대해 서로 다른 명명 된 형식을 사용하는 API 사이의 유행? 어떤 경우에는, gcc가 그 타입 때문에'T2'가'* t1p'에 영향을 줄 수 없기 때문에 gcc가 쓰기를 결정하고,'T1'으로 쓰는 것은 영향을 끼칠 수 없다고 생각합니다. "이미 쓴"(이전의 쓰기가 무시 된 경우에도). – supercat

+0

@supercat은 그럴듯 해 보입니다. 옵티마이 저 코드로 들어가면 확인할 수 있습니다. –