다음 프로그램을 고려하십시오.
#include<stdexcept>
#include<iostream>
int main() {
try {
throw std::range_error(nullptr);
} catch(const std::range_error&) {
std::cout << "Caught!\n";
}
}
libstdc ++를 사용하는 GCC 및 Clang std::terminate
은 메시지와 함께 프로그램을 중단하고 중단합니다
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid
예외 구성시 libc ++ segfault가 포함 된 Clang
godbolt를 참조하십시오 .
컴파일러가 표준을 준수하고 있습니까? 표준의 관련 부분 [diagnostics.range.error] (C ++ 17 N4659)는 그 말 않는 std::range_error
갖는 const char*
오버 선호한다 생성자 과부하 const std::string&
과부하. 이 섹션은 또한 생성자에 대한 전제 조건을 나타내지 않으며 사후 조건 만 나타냅니다.
사후 조건 :
strcmp(what(), what_arg) == 0
.
이 사후 조건 what_arg
은 null 포인터 인 경우 항상 정의되지 않은 동작을 가지고 있으므로 내 프로그램에도 정의되지 않은 동작이 있고 두 컴파일러가 모두 준수한다는 의미입니까? 그렇지 않다면 표준에서 불가능한 사후 조건을 어떻게 읽어야합니까?
두 번째 생각에, 그것은 내 프로그램에 대해 정의되지 않은 동작을 의미한다고 생각합니다. 왜냐하면 그것이 null로 끝나는 문자열을 가리 키지 않는 (유효한) 포인터도 허용되기 때문에 분명히 의미가 없습니다.
그래서 그것이 사실이라고 가정하면, 표준이 어떻게이 정의되지 않은 행동을 내포하는지에 대한 질문에 더 집중하고 싶습니다. 호출에 정의되지 않은 동작이 있거나 전제 조건이 단순히 잊혀진 사후 조건의 불가능 성에서 따릅니 까?
이 질문에서 영감을 얻었습니다 .
nullptr
전달, 난 그 생각 what()
값을 얻기 위해 어떤 시점에서 그것을 역 참조해야합니다. 그것은 문제가 될 수 있고 nullptr
추락하기에 확실한 최악의 경우를 참조하는 것 입니다.
what()
할 때nullptr
아마 문제가 발생할 것입니다 전달됩니다.