💻 Exemplos: Capítulo 07: Lifetimes Estáticos e Explícitos (‘a)
💻 Exemplos: Capítulo 07: Lifetimes e Segurança de Referências
Especialização em Sistemas com Rust • Demonstrações Práticas Compiláveis
🎯 Objetivo dos Exemplos
Apresentar a sintaxe e o propósito dos parâmetros genéricos de tempo de vida (Lifetimes 'a), explicando como o compilador do Rust assegura que nenhuma referência possa apontar para dados já desalocados da memória, eliminando por completo o temido erro de Dangling Pointer.
1. Código Fonte Completo (src/main.rs)
//! Demonstração Prática de Lifetimes Explícitos e o Lifetime Especial 'static
/// Retorna a fatia de string com maior comprimento.
/// O parâmetro genérico <'a> informa ao compilador que a referência retornada
/// viverá pelo menos o tempo mínimo em que tanto 'x' quanto 'y' forem válidos.
fn selecionar_string_mais_longa<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
/// Estrutura que armazena uma referência em vez de ser dona do dado (Zero Copy).
/// O lifetime 'a garante que uma instância de 'ExtratoComando' não pode
/// viver mais tempo do que a string original à qual 'comando' faz referência.
struct ExtratoComando<'a> {
comando: &'a str,
severidade: u8,
}
impl<'a> ExtratoComando<'a> {
fn exibir_relatorio(&self) {
println!(" [Severidade {}] Comando analisado: '{}'", self.severidade, self.comando);
}
}
fn main() {
println!("=== SEGURANÇA DETERMINÍSTICA DE LIFETIMES ===");
// 1. Uso de Função com Lifetimes Anotados
let string1 = String::from("SISTEMA_OPERACIONAL_RUST");
let resultado;
{
let string2 = String::from("KERNEL_CORE");
// string1 e string2 estão vivas neste escopo interno
resultado = selecionar_string_mais_longa(string1.as_str(), string2.as_str());
println!("Mais longa selecionada no escopo interno: '{}'", resultado);
}
// 'string1' ainda vive aqui, mas se 'resultado' dependesse de 'string2'
// e fosse lido fora do escopo de string2, o rustc emitiria erro de compilação!
// 2. Struct com Campos de Referência (Zero Copy)
let payload_rede = String::from("POST /api/v1/auth HTTP/1.1");
let extrato = ExtratoComando {
comando: &payload_rede[0..17], // Slice referenciando o buffer original
severidade: 1,
};
extrato.exibir_relatorio();
// 3. O Lifetime 'static
// Strings literais possuem o lifetime 'static: vivem durante toda a execução
// do programa porque são compiladas diretamente no segmento de dados do binário (ELF/PE).
let constante_sistema: &'static str = "RUST_BARE_METAL_SECURE_BUILD";
println!("\nConstante estática do binário com lifetime 'static: {}", constante_sistema);
// 4. Lifetimes e Elisão Automática
// Em funções com apenas uma referência de entrada, o compilador elide os lifetimes:
let primeira_palavra = obter_primeira_palavra(&payload_rede);
println!("Primeiro verbo HTTP extraído via elisão de lifetimes: '{}'", primeira_palavra);
}
// O compilador aplica a regra de elisão: fn obter_primeira_palavra<'a>(s: &'a str) -> &'a str
fn obter_primeira_palavra(s: &str) -> &str {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[0..i];
}
}
&s[..]
}
2. Saída Esperada no Terminal
=== SEGURANÇA DETERMINÍSTICA DE LIFETIMES ===
Mais longa selecionada no escopo interno: 'SISTEMA_OPERACIONAL_RUST'
[Severidade 1] Comando analisado: 'POST /api/v1/auth'
Constante estática do binário com lifetime 'static: RUST_BARE_METAL_SECURE_BUILD
Primeiro verbo HTTP extraído via elisão de lifetimes: 'POST'