fn dangle() {
fn get_str<'a>(s: *const String) -> &'a str {
unsafe { &*s }
}
let s = String::from("hello");
let dangling = get_str(&s);
drop(s);
println!("Invalid str: {}", dangling);
}
#[test]
fn test() {
dangle(); // it should panic, but does not
}
fn main() {
dangle(); // panics
}
A main()
função entra em pânico, como eu esperava. Mas por que a test()
função roda com sucesso?
Conforme descrito nesta página , seu uso de não
unsafe
é sólido (isso foi feito de propósito na pergunta) e, consequentemente, leva a um comportamento indefinido .Comportamento indefinido não significa que o código necessariamente falhará ou entrará em pânico. Pelo contrário, ele pode fazer qualquer coisa , inclusive funcionar perfeitamente! No meu computador, o programa principal não entra em pânico; ele simplesmente exibe uma string estranha e, ao testá-lo, também não entra em pânico. Mesmo que, no meu computador, o ponteiro não aponte para um endereço inacessível após
drop()
, os bytes neste endereço foram reutilizados para outra coisa, o que parece incorreto quando enviado para a saída padrão. Este comportamento pode mudar de tempos em tempos, dependendo de qualquer coisa no sistema (o sistema, a versão do compilador...).É por isso que códigos inseguros devem ser evitados; só podemos detectar e consertar um problema por acaso (se ele exibir um comportamento incorreto óbvio, como entrar em pânico). Se, por outro lado, o problema simplesmente causar corrupção de dados, ele pode ser detectado muito mais tarde durante a execução, e seria muito difícil descobrir qual foi a causa real do problema (ponteiro pendurado aqui). Essa situação é bem comum em C. O Rust seguro previne que essas armadilhas aconteçam; o Rust inseguro exige que o desenvolvedor mantenha certas garantias.
O que @prog-fh diz.
Só queria acrescentar que, ao trabalhar com
unsafe
código, é altamente recomendável usá-lomiri
durante os testes.miri
é um linter que tenta detectar especificamente código não confiável. Não é garantido que ele encontre tudo, mas ele é muito bom nisso.Para verificar seu código com
miri
, execute:Então, você obtém o seguinte erro: