Funções Inseguras
Chamando Funções Inseguras
Uma função ou método pode ser marcado como unsafe
se houver pré-condições extras que você deve respeitar para evitar comportamento indefinido:
extern "C" { fn abs(input: i32) -> i32; } fn main() { let emojis = "🗻∈🌏"; // SEGURANÇA: Os índices estão na ordem correta, dentro dos limites da // slice da string, e contido dentro da sequência UTF-8. unsafe { println!("emoji: {}", emojis.get_unchecked(0..4)); println!("emoji: {}", emojis.get_unchecked(4..7)); println!("emoji: {}", emojis.get_unchecked(7..11)); } println!("contador de caracteres: {}", count_chars(unsafe { emojis.get_unchecked(0..7) })); // SEGURANÇA: `abs` não lida com ponteiros e não tem nenhum requisito de // segurança. unsafe { println!("Valor absoluto de -3 de acordo com C: {}", abs(-3)); } // Não manter o requerimento de codificação UTF-8 viola segurança de memória! // println!("emoji: {}", unsafe { emojis.get_unchecked(0..3) }); // println!("contador caracter: {}", count_chars(unsafe { // emojis.get_unchecked(0..3) })); } fn count_chars(s: &str) -> usize { s.chars().count() }
Escrevendo Funções Inseguras
Você pode marcar suas próprias funções como inseguras (unsafe
) se elas exigirem condições específicas para evitar comportamentos indefinidos.
/// Troca os valores apontadoes pelos ponteiros fornecidos. /// /// # Segurança /// /// Os ponteiros precisam ser válidos e corretamente alinhados. unsafe fn swap(a: *mut u8, b: *mut u8) { let temp = *a; *a = *b; *b = temp; } fn main() { let mut a = 42; let mut b = 66; // SEGURANÇA: ... unsafe { swap(&mut a, &mut b); } println!("a = {}, b = {}", a, b); }
Chamando Funções Inseguras
get_unchecked
, como a maioria das funções _unchecked
, é insegura, porque pode criar UB se o intervalo estiver incorreto. abs
está incorreto por um motivo diferente: é uma função externa (FFI). Chamar funções externas é geralmente um problema apenas quando essas funções fazem coisas com ponteiros que podem violar o modelo de memória do Rust, mas, em geral, qualquer função C pode ter comportamento indefinido sob quaisquer circunstâncias arbitrárias.
O "C"
neste exemplo é o ABI; outros ABIs também estão disponíveis.
Escrevendo Funções Inseguras
Na verdade, não usaríamos ponteiros para uma função swap
- isto pode ser feito com referências com segurança.
Observe que o código inseguro é permitido dentro de uma função insegura sem um bloco unsafe
. Podemos proibir isso com #[deny(unsafe_op_in_unsafe_fn)]
. Tente adicioná-lo e veja o que acontece. Isso provavelmente mudará em uma edição futura do Rust.