Розглянемо наступну програму:
#include<stdexcept>
#include<iostream>
int main() {
try {
throw std::range_error(nullptr);
} catch(const std::range_error&) {
std::cout << "Caught!\n";
}
}
GCC та Clang з libstdc ++ дзвонять std::terminate
та скасовують програму із повідомленням
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid
Clang з libc ++ segfaults при побудові винятку.
Див godbolt .
Чи відповідають компілятори стандартам? Відповідний розділ стандарту [diagnostics.range.error] (C ++ 17 N4659) дійсно говорить , що std::range_error
має const char*
перевантаження конструктора , який повинен бути кращим за порівнянні з const std::string&
перевантаженням. У розділі також не вказано жодних передумов щодо конструктора, а лише зазначено постумова
Післяумови :
strcmp(what(), what_arg) == 0
.
Ця постійна умова завжди має невизначену поведінку, якщо what_arg
є нульовим покажчиком, то це означає, що моя програма також має невизначене поведінку і що обидва компілятори діють відповідно? Якщо ні, то як слід читати такі неможливі постумови в стандарті?
По-друге, я думаю, що це повинно означати невизначену поведінку для моєї програми, тому що якби тоді (дійсні) вказівники не вказували на нульові завершені рядки, було б також дозволено, що явно не має сенсу.
Отже, припускаючи, що це правда, я хотів би зосередити питання більше на тому, як стандарт передбачає цю невизначену поведінку. Чи випливає це з неможливості постумови, що виклик також має невизначену поведінку або попередня умова була просто забута?
Натхненний цим питанням .
nullptr
це буде прийнято, я б подумав, що what()
доведеться знешкодити його в якийсь момент, щоб отримати значення. Це було б перенаправленням nullptr
, що, в кращому випадку, проблематично, і, безумовно, найважчі.
strcmp
використовується для опису значення what_arg
. Ось так чи інакше йде відповідний розділ зі стандарту С , на який посилається специфікація <cstring>
. Звичайно, формулювання може бути чіткішим.
what()
приnullptr
передачі, ймовірно, спричинить проблеми.