2016-06-10 19 views
1

: ++ (* P)을 수행 할 때포인터를 사용하여 initializer_list에서 C++ 11 요소를 수정하면 SIGSEGV가 발생합니다. 이유가 무엇입니까? I는 다음과 같이 initializer_list 내부 요소를 수정에 const_cast를 사용 하였다

#include <initializer_list> 
int main() 
{ 
    auto a1={1,2,3}; 
    auto a2=a1;//copy or reference? 
    for(auto& e:a1) 
    { 
     int*p=const_cast<int*>(&e); 
     ++(*p); 
    } 
    for(auto& e:a2) 
     cout<<e; 
    return 0; 
} 

불행히도,이 g ++ 4.9.2 컴파일 된 프로그램은 SIGSEGV 던진다. 문제는 VC에서 발생하지 않습니다.

내 프로그램이 안전하지 않은 작업을하는 이유는 무엇입니까? 도와주세요, 고마워요.

+1

'auto a2 = a1; '은 참조가 될 수 없으며 복사본 만 될 것입니다. 참조를 원한다면 'auto & a2 = a1;'과 같이 명시 적으로 입력해야합니다. –

+3

castee에 대해 'const_cast'와 mutation을 수행했는데 프로그램에 "안전하지 않은 연산이 있는지"를 알고 싶습니까? –

답변

3

이전 질문에서 I mentioned으로, initializer_list<T>의 기본 배열은 const 개체로 구성됩니다. const 선언 된 개체 수정 정의되지 않은 동작입니다. [dcl.type.cv]에서 :

수정할 수 있습니다 (7.1.1) 모든 클래스 멤버가 가변 선언 된 것을 제외하고, 수명 (3.8) 정의되지 않은 동작의 결과 중에 CONST 개체를 수정하려는 시도.

정의되지 않은 동작의 가능한 인스턴스 중 하나는 gcc에서 볼 수있는 SIGSEV입니다. 또 다른 가능한 인스턴스 생성은 VC에서 작동하는 코드 작업입니다. 그냥하지 마.

5

초기에 const으로 선언 된 데이터를 수정하는 정의되지 않은 동작이며 이니셜 라이저 목록의 내용은 항상 const입니다.

이 경우 목록의 내용이 읽기 전용 페이지에 저장되어 있고 런타임 오류가 발생하는 것 같습니다. 운이 좋다 : 정의되지 않은 동작이있다 무엇이든이 일어날 수있다.

const에 쓰는 것에 의한 정의되지 않은 동작의 또 다른 예는 한 줄에서 무언가를 수정할 때 발생합니다. 다음 줄에서는 수정 내용이 표시되지 않습니다. 이는 컴파일러가 const로 선언 된 (참조되지 않은) 데이터 을 변경하지 않는다고 가정 할 수 있기 때문에 발생합니다. 따라서 초기 값이 항상 가지고있는 값이라고 추정하도록 코드를 최적화 할 수 있습니다. 실제로 컴파일러는 할

다른 가능성은 조건이 다른 설정해야합니다 분기 를 입력 할 것을 유도, 분기에 분기가 논리적으로 수행 할 수없는 이유를 정의되지 않은 동작을하고 몰래 및 제거 컴파일러입니다 전적으로 지점 (및/또는 위의 논리에 의해 전제 조건이 입증 된 지점으로 이동). 정의되지 않은 동작은 시간 여행을 할 수 있습니다.

하드 드라이브를 포맷 할 수 있고 컴퓨터가 폭발 할 수 있으며 웹 기록을 학부모에게 이메일로 보냅니다. 컴파일러는 코드가 원하는대로 또는 무엇이든 할 수 있도록 언제든지 자유롭게 할 수 있습니다.

정의되지 않은 동작을 수행하지 마십시오.