Considere o seguinte programa:
#include<stdexcept>
#include<iostream>
int main() {
try {
throw std::range_error(nullptr);
} catch(const std::range_error&) {
std::cout << "Caught!\n";
}
}
GCC e Clang com chamada libstdc ++ std::terminate
e aborte o programa com a mensagem
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid
Clang com libc ++ segfaults na construção da exceção.
Veja Godbolt .
Os compiladores estão se comportando em conformidade com o padrão? A seção relevante do padrão [diagnostics.range.error] (C ++ 17 N4659) diz que std::range_error
possui uma const char*
sobrecarga de construtor que deve ser preferida à const std::string&
sobrecarga. A seção também não declara pré-condições no construtor e apenas a pós-condição
Pós-condições :
strcmp(what(), what_arg) == 0
.
Essa pós-condição sempre tem um comportamento indefinido se what_arg
for um ponteiro nulo; isso significa que meu programa também tem um comportamento indefinido e que os dois compiladores agem em conformidade? Caso contrário, como se deve ler essas pós-condições impossíveis no padrão?
Pensando bem, acho que deve significar um comportamento indefinido para o meu programa, porque, se isso não significasse, ponteiros (válidos) que não apontam para seqüências terminadas em nulo também seriam permitidos, o que claramente não faz sentido.
Então, supondo que isso seja verdade, eu gostaria de focar mais a questão em como o padrão implica esse comportamento indefinido. Resulta da impossibilidade da pós-condição que a chamada também tenha um comportamento indefinido ou a pré-condição foi simplesmente esquecida?
Inspirado por esta pergunta .
nullptr
for aprovada, eu acho que what()
teria que desreferenciar isso em algum momento para obter o valor. Isso seria desreferenciar a nullptr
, o que é problemático na melhor das hipóteses e com certeza travar é o pior.
strcmp
é usada para descrever o valor de what_arg
. É o que a seção relevante do padrão C diz de qualquer maneira, a que se refere a especificação de <cstring>
. Claro que o texto poderia ser mais claro.
what()
quandonullptr
é passado provavelmente causaria problemas.