Considérez le programme suivant:
#include<stdexcept>
#include<iostream>
int main() {
try {
throw std::range_error(nullptr);
} catch(const std::range_error&) {
std::cout << "Caught!\n";
}
}
GCC et Clang avec libstdc ++ appellent std::terminate
et abandonnent le programme avec le message
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid
Clang avec libc ++ segfaults sur la construction de l'exception.
Voir godbolt .
Les compilateurs se comportent-ils conformément aux normes? La section pertinente de la norme [diagnostics.range.error] (C ++ 17 N4659) dit qu'il y std::range_error
a une const char*
surcharge de constructeur qui devrait être préférée à la const std::string&
surcharge. La section n'énonce pas non plus de conditions préalables sur le constructeur et indique uniquement la postcondition
Postconditions :
strcmp(what(), what_arg) == 0
.
Cette postcondition a toujours un comportement indéfini s'il what_arg
s'agit d'un pointeur nul, cela signifie-t-il que mon programme a également un comportement indéfini et que les deux compilateurs agissent conformément? Sinon, comment lire ces conditions postérieures impossibles dans la norme?
À la réflexion, je pense que cela doit signifier un comportement indéfini pour mon programme, car si ce n'était pas le cas, des pointeurs (valides) ne pointant pas vers des chaînes terminées par null seraient également autorisés, ce qui n'a clairement aucun sens.
Donc, en supposant que cela soit vrai, je voudrais concentrer davantage la question sur la façon dont la norme implique ce comportement indéfini. Doit-il résulter de l'impossibilité de la postcondition que l'appel a également un comportement indéfini ou la condition préalable a-t-elle simplement été oubliée?
Inspiré par cette question .
nullptr
est passé, je pense qu'il what()
faudrait le déréférencer à un moment donné pour obtenir la valeur. Ce serait déréférencer un nullptr
, ce qui est au mieux problématique et certain de planter est pire.
strcmp
est utilisé pour décrire la valeur de what_arg
. C'est ce que dit de toute façon la section pertinente de la norme C , à laquelle fait référence la spécification de <cstring>
. Bien sûr, le libellé pourrait être plus clair.
what()
quandnullptr
est passé causerait probablement des problèmes.