<h2>Entendendo Unsafe Rust</h2>
<p>Unsafe Rust é um subconjunto da linguagem que permite operações que o compilador não consegue verificar automaticamente. Contrariamente ao que muitos acreditam, "unsafe" não significa "sem segurança" — significa que <strong>você assume a responsabilidade</strong> de garantir a segurança. O compilador confia em você para não introduzir comportamentos indefinidos (undefined behavior).</p>
<p>A razão de existir é prática: algumas operações são necessárias em sistemas de baixo nível, chamadas de funções C, manipulação de ponteiros e otimizações críticas. Rust oferece as ferramentas, mas exige que você entenda as consequências. Isso é um contrato entre você e a linguagem.</p>
<h2>Operações Unsafe Principais</h2>
<h3>Desreferenciar Ponteiros Brutos</h3>
<p>Ponteiros brutos (<code><em>const T</code> e <code></em>mut T</code>) ignoram as regras de borrowing do Rust. Você pode ter múltiplos ponteiros mutáveis apontando para o mesmo local, causando data races se não tiver cuidado. Desreferenciar um ponteiro inválido é undefined behavior.</p>
<pre><code class="language-rust">fn main() {
let x = 5;
let raw_ptr = &x as *const i32;
unsafe {
println!("Valor: {}", *raw_ptr); // Válido, aponta para x
}
}</code></pre>
<p>Este exemplo é seguro porque sabemos que <code>raw_ptr</code> aponta para <code>x</code> durante toda sua vida útil. Porém, nunca dereference um ponteiro nulo ou inválido.</p>
<h3>Chamar Funções Unsafe</h3>
<p>Funções externas (FFI) e algumas funções Rust marcadas como <code>unsafe</code> precisam estar dentro de blocos unsafe. A função sinaliza: "eu tenho precondições que você deve garantir".</p>
<pre><code class="language-rust">extern "C" {
fn strlen(s: *const u8) -> usize;
}
fn main() {
let c_string = b"hello\0";
unsafe {
let len = strlen(c_string.as_ptr());
println!("Comprimento: {}", len);
}
}</code></pre>
<p>Aqui, <code>strlen</code> requer que o ponteiro seja válido e termine com <code>\0</code>. É sua responsabilidade garantir isso. Se passar um ponteiro inválido, comportamento indefinido ocorrerá.</p>
<h3>Mutabilidade Estática e Raw Pointers</h3>
<p>Variáveis estáticas mutáveis são inerentemente thread-unsafe. Acessá-las exige <code>unsafe</code> porque múltiplas threads podem modificá-las simultaneamente.</p>
<pre><code class="language-rust">static mut COUNTER: i32 = 0;
fn increment() {
unsafe {
COUNTER += 1;
}
}
fn main() {
increment();
unsafe {
println!("Contador: {}", COUNTER);
}
}</code></pre>
<p>Se você precisar de um contador thread-safe, use <code>std::sync::atomic::AtomicI32</code> em vez disso — é seguro e não requer <code>unsafe</code>.</p>
<h2>Quando Usar (e Não Usar) Unsafe</h2>
<h3>Casos Legítimos</h3>
<p>Use unsafe apenas quando for <strong>absolutamente necessário</strong>: integração com C, implementar estruturas de dados de baixo nível (alocadores customizados, concorrência primitiva), ou quando a performance crítica é bloqueadora. Mesmo assim, minimize o escopo do bloco <code>unsafe</code>.</p>
<pre><code class="language-rust">pub struct RawBuffer {
ptr: *mut u8,
capacity: usize,
}
impl RawBuffer {
pub fn new(capacity: usize) -> Self {
let ptr = unsafe {
std::alloc::alloc(std::alloc::Layout::from_size_align_unchecked(
capacity, 1
)) as *mut u8
};
RawBuffer { ptr, capacity }
}
pub fn get(&self, index: usize) -> Option<u8> {
if index < self.capacity {
unsafe { Some(*self.ptr.add(index)) }
} else {
None
}
}
}
impl Drop for RawBuffer {
fn drop(&mut self) {
unsafe {
std::alloc::dealloc(
self.ptr,
std::alloc::Layout::from_size_align_unchecked(
self.capacity, 1
)
);
}
}
}</code></pre>
<p>Este exemplo encapsula a complexidade: o API público é totalmente seguro, e <code>unsafe</code> fica contido internamente com verificações adequadas.</p>
<h3>Antipadrões Comuns</h3>
<p>Não use <code>unsafe</code> para:</p>
<ul>
<li><strong>Ignorar o type system</strong>: Se o compilador reclama, há uma razão.</li>
<li><strong>Ganho de performance especulativo</strong>: Meça primeiro. <code>unsafe</code> muitas vezes não oferece ganhos reais.</li>
<li><strong>Contornar regras de borrowing</strong> porque "você sabe melhor": Você provavelmente não sabe. As regras existem por razão.</li>
</ul>
<h2>Boas Práticas e Responsabilidade</h2>
<p>Quando você escreve <code>unsafe</code>, coloque um comentário detalhado explicando <strong>por que</strong> é seguro. Isso ajuda revisores de código e você mesmo no futuro.</p>
<pre><code class="language-rust">pub fn safe_slice_from_raw(ptr: *const u8, len: usize) -> Option<&'static [u8]> {
unsafe {
// SEGURANÇA: Requer que ptr aponte para len bytes válidos e inicializados,
// e que permaneçam válidos por 'static. Chamador deve garantir.
if ptr.is_null() {
return None;
}
Some(std::slice::from_raw_parts(ptr, len))
}
}</code></pre>
<p>Docummente as precondições. Use tipos que forçam segurança quando possível: <code>Option<T></code>, <code>Result<T, E></code>, tipos phantom para lifetime tracking. Teste com <code>cargo test</code> e ferramentas como Miri para detectar undefined behavior.</p>
<pre><code class="language-bash">cargo +nightly miri test</code></pre>
<p>Miri emula execução Rust e detecta muitos erros de unsafe que passariam despercebidos.</p>
<h2>Conclusão</h2>
<p>Unsafe Rust não é o vilão — é uma ferramenta específica para casos específicos. Lembre-se de três pontos críticos: <strong>(1)</strong> Use <code>unsafe</code> apenas quando absolutamente necessário e minimize seu escopo; <strong>(2)</strong> Documente rigorosamente as precondições e invariantes; <strong>(3)</strong> Encapsule unsafe em APIs seguras quando possível, deixando complexidade para dentro.</p>
<p>O compilador Rust protege você 99% do tempo. Quando você entra em territorio unsafe, você assume esse 1% restante. Use essa responsabilidade com sabedoria.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html" target="_blank" rel="noopener noreferrer">The Rust Book — Unsafe Rust</a></li>
<li><a href="https://doc.rust-lang.org/nomicon/" target="_blank" rel="noopener noreferrer">The Rustonomicon — Unsafe Code</a></li>
<li><a href="https://github.com/rust-lang/miri" target="_blank" rel="noopener noreferrer">Miri Interpreter for Undefined Behavior Detection</a></li>
<li><a href="https://rust-lang.github.io/api-guidelines/" target="_blank" rel="noopener noreferrer">Rust API Guidelines — Safety</a></li>
<li><a href="https://www.youtube.com/watch?v=QAz-maaH0KE" target="_blank" rel="noopener noreferrer">Jon Gjengset — Crust of Rust: Unsafe Code</a></li>
</ul>