Pertimbangkan program berikut:
#include<stdexcept>
#include<iostream>
int main() {
try {
throw std::range_error(nullptr);
} catch(const std::range_error&) {
std::cout << "Caught!\n";
}
}
GCC dan Dentang dengan libstdc ++ panggilan std::terminate
dan batalkan program dengan pesan
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid
Dibatasi dengan libc ++ segfault pada konstruksi pengecualian.
Lihat godbolt .
Apakah kompiler berperilaku sesuai standar? Bagian yang relevan dari standar [diagnosticics.range.error] (C ++ 17 N4659) memang mengatakan bahwa std::range_error
memiliki const char*
kelebihan konstruktor yang harus dipilih lebih dari const std::string&
kelebihan. Bagian ini juga tidak menyatakan prasyarat apa pun pada konstruktor dan hanya menyatakan prasyarat tersebut
Postconditions :
strcmp(what(), what_arg) == 0
.
Postcondition ini selalu memiliki perilaku yang tidak terdefinisi jika what_arg
adalah null pointer, jadi apakah ini berarti bahwa program saya juga memiliki perilaku yang tidak terdefinisi dan bahwa kedua kompiler bertindak sesuai? Jika tidak, bagaimana seharusnya seseorang membaca postconditions yang tidak mungkin dalam standar?
Setelah dipikir-pikir, saya pikir itu harus berarti perilaku yang tidak terdefinisi untuk program saya, karena jika tidak maka pointer (valid) yang tidak menunjuk ke string null juga akan diizinkan, yang jelas tidak masuk akal.
Jadi, dengan asumsi itu benar, saya ingin memfokuskan pertanyaan lebih pada bagaimana standar menyiratkan perilaku yang tidak terdefinisi ini. Apakah itu mengikuti dari ketidakmungkinan postkondisi bahwa panggilan itu juga memiliki perilaku yang tidak terdefinisi atau apakah prasyarat itu dilupakan begitu saja?
Terinspirasi oleh pertanyaan ini .
nullptr
dilewati, saya akan berpikir bahwa saya what()
harus melakukan dereferensi di beberapa titik untuk mendapatkan nilai. Itu akan menjadi dereferencing nullptr
, yang paling bermasalah dan pasti untuk crash adalah yang terburuk.
strcmp
digunakan untuk menggambarkan nilai what_arg
. Itulah yang dikatakan bagian yang relevan dari standar C , yang disebut dengan spesifikasi <cstring>
. Tentu saja kata-katanya bisa lebih jelas.
what()
saatnullptr
diteruskan mungkin akan menyebabkan masalah.