Considera il seguente programma:
#include<stdexcept>
#include<iostream>
int main() {
try {
throw std::range_error(nullptr);
} catch(const std::range_error&) {
std::cout << "Caught!\n";
}
}
GCC e Clang con libstdc ++ chiamano std::terminate
e interrompono il programma con il messaggio
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid
Clang con libc ++ segfaults alla costruzione dell'eccezione.
Vedi godbolt .
I compilatori si comportano secondo standard? La sezione pertinente dello standard [diagnostics.range.error] (C ++ 17 N4659) afferma che std::range_error
ha un const char*
sovraccarico del costruttore che dovrebbe essere preferito rispetto al const std::string&
sovraccarico. La sezione inoltre non indica alcuna condizione preliminare per il costruttore e indica solo la postcondizione
Postcondizioni :
strcmp(what(), what_arg) == 0
.
Questa postcondizione ha sempre un comportamento indefinito se what_arg
è un puntatore nullo, quindi questo significa che anche il mio programma ha un comportamento indefinito e che entrambi i compilatori agiscono in modo conforme? In caso contrario, come si dovrebbero leggere tali postcondizioni impossibili nello standard?
A pensarci bene, penso che debba significare un comportamento indefinito per il mio programma, perché se non lo facesse allora anche i puntatori (validi) che non puntano a stringhe con terminazione nulla sarebbero ammessi, il che chiaramente non ha senso.
Quindi, supponendo che sia vero, vorrei focalizzare maggiormente la domanda su come lo standard implichi questo comportamento indefinito. Dall'impossibilità della postcondizione deriva che anche la chiamata ha un comportamento indefinito o la precondizione è stata semplicemente dimenticata?
Ispirato da questa domanda .
nullptr
viene passato, penso che what()
dovrebbe dereferenziarlo ad un certo punto per ottenere il valore. Questo sarebbe il dereferenziamento di a nullptr
, che è problematico nella migliore delle ipotesi e sicuramente il crash è il peggiore.
strcmp
viene usato per descrivere il valore di what_arg
. Questo è ciò che dice comunque la sezione pertinente dello standard C , a cui fa riferimento la specifica di <cstring>
. Naturalmente la formulazione potrebbe essere più chiara.
what()
quandonullptr
viene passato probabilmente causerebbe problemi.