Hãy xem xét chương trình sau:
#include<stdexcept>
#include<iostream>
int main() {
try {
throw std::range_error(nullptr);
} catch(const std::range_error&) {
std::cout << "Caught!\n";
}
}
GCC và Clang với libstdc ++ gọi std::terminate
và hủy bỏ chương trình với thông báo
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid
Clang với libc ++ segfaults về xây dựng ngoại lệ.
Xem thần thánh .
Là các trình biên dịch hành xử phù hợp tiêu chuẩn? Phần có liên quan của tiêu chuẩn [chẩn đoán.range.error ] (C ++ 17 N4659) có nói rằng std::range_error
có const char*
quá tải hàm tạo nên được ưu tiên hơn const std::string&
quá tải. Phần này cũng không nêu bất kỳ điều kiện tiên quyết nào trên hàm tạo và chỉ nêu phần hậu điều kiện
Hậu điều :
strcmp(what(), what_arg) == 0
.
Postcondition này luôn có hành vi không xác định nếu what_arg
là con trỏ null, vì vậy điều này có nghĩa là chương trình của tôi cũng có hành vi không xác định và cả hai trình biên dịch đều tuân thủ? Nếu không, làm thế nào người ta nên đọc các điều kiện không thể như vậy trong tiêu chuẩn?
Về ý nghĩ thứ hai, tôi nghĩ nó phải có nghĩa là hành vi không xác định cho chương trình của tôi, bởi vì nếu nó không (thì hợp lệ) con trỏ không trỏ đến chuỗi kết thúc null cũng sẽ được cho phép, điều này rõ ràng là vô nghĩa.
Vì vậy, giả sử đó là sự thật, tôi muốn tập trung vào câu hỏi nhiều hơn về cách tiêu chuẩn ngụ ý hành vi không xác định này. Liệu nó xuất phát từ sự bất khả thi của postcondation rằng cuộc gọi cũng có hành vi không xác định hoặc là điều kiện tiên quyết bị lãng quên?
Lấy cảm hứng từ câu hỏi này .
nullptr
được thông qua, tôi sẽ nghĩ rằng what()
sẽ phải hủy bỏ nó vào một lúc nào đó để có được giá trị. Đó sẽ là cuộc hội thảo a nullptr
, đó là vấn đề tốt nhất và chắc chắn để sụp đổ là tồi tệ nhất.
strcmp
được sử dụng để mô tả giá trị của what_arg
. Đó là những gì phần có liên quan từ tiêu chuẩn C nói dù sao, được đề cập bởi đặc điểm kỹ thuật của <cstring>
. Tất nhiên các từ ngữ có thể rõ ràng hơn.
what()
khinullptr
được thông qua có thể sẽ gây ra vấn đề.