No description
Find a file
2026-08-14 07:12:28 +02:00
.woodpecker chore: migrate CI to .woodpecker/{push,branch}.yml 2026-08-14 07:12:28 +02:00
src initial content 2026-08-14 07:12:17 +02:00
tests initial content 2026-08-14 07:12:17 +02:00
.gitignore Initial commit 2026-08-14 05:11:19 +00:00
Cargo.lock initial content 2026-08-14 07:12:17 +02:00
Cargo.toml chore: declare MSRV 1.85 (edition 2024) 2026-08-14 07:12:28 +02:00
LICENSE chore: add AGPL-3.0 license and standard .gitignore 2026-08-14 07:12:28 +02:00
README.md fix(011): pedagogical MINOR fixes (forward-refs, test strength, contract docs) 2026-08-14 07:12:28 +02:00

Lição 11: Memória de Batalha

Narrativa

Piloto, hoje você vai entender como seu mecha gerencia a memória durante uma batalha. Imagine que cada sistema do mecha tem um "painel de memória" com duas áreas: a Stack (memória rápida para dados pequenos e fixos) e o Heap (memória dinâmica para dados que crescem durante o combate).

Quando você pilota um mecha, cada dado precisa ser alocado em algum lugar. Dados simples como números inteiros vão direto para a Stack — rápido e eficiente. Mas quando você precisa armazenar textos ou dados complexos, o sistema aloca no Heap, que é mais flexível mas exige gerenciamento cuidadoso.

Um bom piloto sabe exatamente onde cada peça de informação está armazenada. Vamos treinar essa habilidade.

Conceito

Stack (Pilha):

  • Memória rápida, alocada em ordem LIFO (Last In, First Out)
  • Dados com tamanho fixo e conhecido em tempo de compilação
  • Gerenciamento automático — não precisa liberar manualmente
  • Exemplos: inteiros, booleanos, floats, caracteres

Heap (Montão):

  • Memória dinâmica, alocada quando necessário
  • Dados de tamanho variável ou desconhecido
  • Em Rust, usamos Box<T> para alocar no heap
  • Não é necessário chamar drop explicitamente — o RAII (Drop trait) cuida da liberação automaticamente
// Stack - dado fixo
let velocidade: i32 = 100;  // Stack, 4 bytes

// Heap - dado dinâmico via Box
let nome: Box<String> = Box::new(String::from("Excalibur"));

Nota (conceito futuro): Box<T> é explorado a fundo na Lição 037 (Tipos Box). Aqui usamos Box<String> apenas por razões pedagógicas — para demonstrar a alocação no heap. Em produção, Box<String> é um anti-padrão (heap dentro de heap), pois String já aloca seu conteúdo no heap; o Box externo adiciona uma indireção desnecessária. Nesta lição, aceite essa redundância para visualizar claramente a diferença entre stack e heap.

Em Rust, o ownership determina quando a memória é liberada. Dados na stack são copiados (Copy trait). Dados no heap são movidos ou clonados.

Requisitos

  • Entrada: Valores para alocar (i32, String, Box)
  • Processamento: Alocar, copiar e liberar memória
  • Saída: Resultados das operações de memória

Design de Dados

// Funções que demonstram alocação de memória
pub fn alocar_stack(valor: i32) -> i32;
pub fn alocar_heap(dado: &str) -> Box<String>;
pub fn copiar_stack(original: i32) -> i32;
pub fn copiar_heap(dado: &str) -> String;
pub fn liberar_memoria(dado: Box<String>);

Diagrama Conceitual

flowchart TD
    A[Valor Simples] --> B[Stack]
    A --> C[Heap via Box]
    B --> D[Copiado automaticamente]
    C --> E[Clonado ou movido]
    D --> F[Liberação automática]
    E --> G[Drop trait chamado]

Funções e Módulos

/// Aloca um valor simples na stack (dados com tamanho conhecido)
pub fn alocar_stack(valor: i32) -> i32;

/// Aloca dados dinamicamente no heap usando Box
pub fn alocar_heap(dado: &str) -> Box<String>;

/// Copia um valor da stack (tipos Copy)
pub fn copiar_stack(original: i32) -> i32;

/// Clona dados do heap (tipos que não são Copy)
pub fn copiar_heap(dado: &str) -> String;

/// Libera memória do heap (Drop implícito em Box)
pub fn liberar_memoria(dado: Box<String>);

Exemplo do Conceito

fn main() {
    // Stack - inteiro simples
    let a: i32 = 42;  // Alocado na stack
    let b = a;        // Cópia na stack (Copy trait)
    println!("a = {}, b = {}", a, b);  // Ambos válidos

    // Heap - String via Box
    let dados: Box<String> = Box::new(String::from("dados importantes"));
    println!("{:?}", dados);  // Box<String> imprime o conteúdo interno

    // Box é automaticamente liberado quando sai do escopo
}

Missão

  1. Implementar alocar_stack: Retorne o valor recebido (dados Copy via stack)
  2. Implementar alocar_heap: Crie um Box<String> com o dado recebido
  3. Implementar copiar_stack: Retorne uma cópia do valor (Copy semantics)
  4. Implementar copiar_heap: Retorne um clone da string (Clone semantics)
  5. Implementar liberar_memoria: Função que não faz nada — Box libera automaticamente
flowchart TD
    A[Testes] --> B[alocar_stack]
    B --> C[alocar_heap]
    C --> D[copiar_stack]
    D --> E[copiar_heap]
    E --> F[liberar_memoria]

Como Executar

cargo test
cargo clippy -- -D warnings
cargo fmt --check

Dicas

  • Dados Copy (i32, bool, char, f32, f64) são sempre copiados na stack
  • String e Box NÃO são Copy — usam Heap
  • .clone() cria uma cópia deep no heap
  • Box é automaticamente dropado quando sai do escopo
  • Não use unwrap() em produção — apenas em testes