your programing

다소 간단한 C ++ 11 프로그램을 컴파일 할 때 gcc와 clang 사이의 다른 결과

lovepro 2020. 12. 31. 23:06
반응형

다소 간단한 C ++ 11 프로그램을 컴파일 할 때 gcc와 clang 사이의 다른 결과


이 간단한 C ++ 11 프로그램의 출력에서 ​​gcc와 clang에 의해 노출 된 다른 동작이 clang (Xcode 5.0.2, OS X 10.8.5)의 버그 때문인지 이해하려고합니다. 코드는 다음과 같습니다.

#include <iostream>

int main() {


    int matrix[][3]{{1,2,3}, {4,5,6}, {7,8,9}};
    auto dyn_matrix = new int[3][3]{{1,2,3}, {4,5,6}, {7,8,9}};

    std::cout << matrix[0][1] << std::endl;
    std::cout << dyn_matrix[0][1] << std::endl;

    return 0;   
}

표시된대로, 균일 한 초기화를 사용하여 size의 익명 (각각 명명 된) 다차원 배열을 초기화하려고합니다 3x3. MacPorts에서 gcc 4.7로 컴파일 할 때 예상되는 출력을 얻습니다.

$g++-mp-4.7 -std=c++11 dyn_matrix.cpp -o dyn_matrix 
$ ./dyn_matrix
2
2
$

반대로 clang이 사용되는 경우 출력은 다음과 같습니다.

$ clang++ -std=c++11 -stdlib=libc++ dyn_matrix.cpp -o dyn_matrix_clang
$ ./dyn_matrix_clang 
2
4
$  

이 경우 결과는 (분명히) 잘못되었습니다. clang --version보고서 :

Apple LLVM version 5.0 (clang-500.2.75) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix

누구를 비난할까요? 나, gcc 또는 clang?

2013 년 12 월 11 일 업데이트 : r196995에서 버그가 수정되었을 것입니다. 불행히도 Apple이 Xcode와 함께 제공되는 clang 버전을 업데이트하기까지 얼마나 걸릴지 아직 모릅니다.

업데이트 2013 년 12 월 9 일 : LLVM 버그질라 플랫폼에 대한 버그 보고서를 제출했습니다. 실제로 버그로 인식되었으며 현재 패치가 검토 중 입니다. http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20131209/095099.html을 참조 하십시오 .

감사.


업데이트 : Faisal Vali와 Richard Smith 덕분에이 버그는 Clang ToT에서 수정되었습니다. 커밋에 의해 도입 된 테스트 파일을 참조하십시오 .


§8.5.1 [dcl.init.aggr] 에 따르면 Clang이 잘못된 것으로 보입니다.

11 / 다음과 같이 initializer-list 에서 중괄호를 제거 할 수 있습니다 . 경우 초기화 목록이 왼쪽 중괄호로 시작, 다음의 성공 쉼표로 구분 된 목록 초기화-절은 subaggregate의 멤버를 초기화한다; 멤버 보다 initializer 절이 더 많은 것은 잘못된 것입니다. 그러나 하위 집계에 대한 initializer-list 가 왼쪽 중괄호로 시작하지 않으면 목록에서 충분한 initializer-clause가져 와서 하위 집계의 멤버를 초기화합니다. 나머지 initializer-clauses 는 현재 하위 집계가 멤버 인 집계의 다음 멤버를 초기화하기 위해 남겨집니다. [ 예 :

float y[4][3] = {
    { 1, 3, 5 },
    { 2, 4, 6 },
    { 3, 5, 7 },
};

완전 - 보강 초기화 : 1, 3, 5는 어레이의 첫번째 행의 초기화 y[0], 즉 y[0][0], y[0][1], 및 y[0][2]. 마찬가지로 다음 두 줄은 y[1]y[2]. 이니셜 라이저는 일찍 종료되므로 y[3]s 요소는 형식의 표현식으로 명시 적으로 초기화 된 것처럼 float()초기화됩니다 0.0. 즉,로 초기화됩니다 . 다음 예에서는 initializer-list의 중괄호가 제거되었습니다 . 그러나 initializer-list위의 예제 에서 완전히 중괄호로 묶인 initializer-list 와 동일한 효과를 가지고 있습니다.

float y[4][3] = {
    1, 3, 5, 2, 4, 6, 3, 5, 7
};

y에 대한 이니셜 라이저는 왼쪽 중괄호로 시작하지만 for y[0]는 그렇지 않으므로 목록의 세 요소가 사용됩니다. 마찬가지로 다음 세 개는 y[1]및에 대해 연속적으로 사용됩니다 y[2]. 최종 예 ]

§5.3.4 [expr.new] 때문에 적용되는 것 같습니다.

15 / T 유형의 객체를 생성하는 새로운 표현식 은 다음과 같이 해당 객체를 초기화합니다.

  • 는 IF 새로운 초기화가 생략되어, 객체는 기본 초기화 (인 §8.5 ); 초기화가 수행되지 않으면 개체의 값이 결정되지 않습니다.
  • 그렇지 않으면 직접 초기화를 위해 §8.5 의 초기화 규칙에 따라 새 초기화 프로그램 이 해석됩니다 .

ReferenceURL : https://stackoverflow.com/questions/20452967/different-results-between-gcc-and-clang-when-compiling-a-rather-simple-c11-pro

반응형