2010-08-02 5 views
8

나는 lvalue를 :: delete로 전달한 첫 번째 컴파일러를 만났지만 lvalue는 제로화하지 않았습니다. 다음이 참입니다.어디 C + + 표준 않습니다 말 : :: 삭제 lvalues ​​변경할 수 있습니까?

Foo * p = new Foo(); 
Foo * q = p; 
assert(p != 0); 
assert(p == q); 
::delete p; 
assert(p != q); 
assert(p != 0); 

삭제 작업 후에 p는 0이 아니며 이전 값에서 변경되었습니다. 동료는 p를 0xFFFFFFFF로 변경하는 일부 메인 프레임 C++ 컴파일러와 p를 0으로 변경하는 다른 컴파일러에서 작업 한 경험이 드문 것이 아니라고 말했습니다.

C++ 표준에서 말하는 곳은 어디입니까? 컴파일러는 이것을 할 수 있습니까? Why doesn’t delete set the pointer to NULL? 문 포함하는 Bjarne Stroustrup's response라고 대답했다 : StackOverflow의를 통해 검색

, 나는이 질문을 발견

C가 명시 적으로 좌변 피연산자를 제로로 삭제의 구현을 허용 ++를, 내가했다 그 구현은 그렇게 할 수 있기를 희망했지만, 그 아이디어는 구현 자들에게 인기가 없었던 것처럼 보인다.

final committee draft C++0x standard의 5.3.5 및 12.5 섹션을 읽고 다시 읽었지만 "명시적인"부분이 보이지 않습니다. 표준의 잘못된 부분을보고 있습니까? 또는 섹션에있는 논리 체인이 있지만 제대로 연결되어 있지 않습니다.

필자는 Annotated C++ Reference Manual을 더 이상 가지고 있지 않습니다. 컴파일러가 할 수있는 ARM에 있었습니까?

[편집 : 섹션 참조를 3.5.3에서 5.3.5로 수정. 또한 p가 삭제 후에 정의되지 않는다는 헨크의 주장과 대립되는 흥미로운 역설을 추가하고 있습니다.]

p가 null로 초기화되면 흥미로운 역설이 생깁니다.

Foo * p = 0; 
Foo * q = p; 
assert(p == 0); 
assert(p == q); 
::delete p; 
assert(p == q); 
assert(p == 0); 

이 경우에도 동작은 잘 문서화되어 있습니다. delete가 널 포인터를 얻었을 때, 아무 일도하지 않는 것으로 가정하므로 p는 변경되지 않습니다.

+0

음, ARM도 여기에 없으며 거기에 없습니다. 그리고 lvalues를 잊어 버리자. 귀하의 질문은 "삭제할 수 있습니다 그것의 인수 변경?"입니다. –

+0

또한 표준은 컴파일러가 무엇을 할 수 있는지에 대해 크게 중요하지 않습니다. 컴파일러는해야 할 일과해서는 안되는 것만 지정합니다. 포인터 값이 변경되는 것을 금지하는 현재 표준에서는 아무것도 볼 수 없습니다. –

+1

나는 내 질문을 "삭제할 수 있습니까? 왜냐하면 나는 void * 및 void **가 아닌 void * 만 취하기 때문에 연산자 삭제 지원이 그 인자를 어떻게 바꾸는지를 어떻게 선언 할 것인가에 대해 원하지 않기 때문입니다. – Ants

답변

8

너무 명확하지 않을 수 있습니다. 5.3.5/7에서는 delete 표현식이 deallocator 함수를 호출한다고합니다. 3.7.3.2/4에서는 할당이 해제 된 포인터를 사용하는 것이 정의되지 않는다고 말합니다. 할당 해제 후 포인터의 값을 사용할 수 없기 때문에 포인터가 값을 유지하는지 또는 구현에 의해 값이 변경되는지 여부가 달라지지 않습니다.

5.3.5/7

삭제가 식은 해제 기능 (3.7.3.2)를 호출한다. 표준 라이브러리에서 해제 기능에 주어진 인수는 널 포인터 값하지 않은 포인터 (4.10), 할당 해제 기능이 저장 할당을 해제한다 인 경우

3.7.3.2/4

할당되지 않은 저장 영역의 일부를 참조하는 모든 포인터를 유효하지 않게 렌더링합니다. 유효하지 않은 포인터 값을 사용하는 효과 (할당 해제 함수에 전달하는 것을 포함)는 정의되지 않음.

참고 자료는 현재 표준에서 나온 것입니다. 곧 표준에서 5.3.5/7 재 진술하고있다 :

C++ 0X에게 FD 5.3.5/7

을 삭제 표현의 피연산자의 값이 널 포인터 값이 아닌 경우 , delete-expression은 할당 해제 함수를 호출합니다 (3.7.4.2). 그렇지 않으면 할당 해제 함수가 호출되는지 여부는 지정되지 않습니다. [참고 : deallocation 함수는 객체의 소멸자 또는 배열의 일부 요소가 예외를 throw하는지 여부에 관계없이 호출됩니다. - 끝 노트]

+0

좋아요, 저는 이것을 내 요점으로 생각합니다. 유효하지 않은 포인터를 사용하면 정의되지 않은 스마트 컴파일러는 유효하지 않은 포인터를 변경할 수 있으므로 오류가 더 잘 표시됩니다. 빨리 실패하고, 일찍 실패하십시오. –

+2

@Henk : "실패 빠른, 실패 초기"철학을 지원하는 컴파일러의 의도에 완전히 동의합니다. 거의 10 년 동안 선적 된 코드의 버그가 노출되었습니다. 노드의 소멸자에서 다음, 이전 및 첫 번째 노드 포인터를 자동으로 업데이트하는 이중 연결 목록 구현이 있습니다. 목록의 소멸자는 "while (m_firstNode) delete m_firstNode;"로 코딩되었습니다. 노드 소멸자가 m_firstNode를 올바르게 업데이트하지만 소멸자 호출 후에 0이 아닌 값으로 컴파일러가 m_firstNode를 덮어 씁니다. Kaboom! 명시적인 경우 원본 코드가 달라졌을 것입니다. – Ants

+0

@Ants : 흥미 롭습니다. 이렇게하면 가장자리로 이동하여 믹스에 앨리어싱을 추가합니다. –

관련 문제