Revisão da Memória de Programa
Os programas alocam memória de duas maneiras:
-
Pilha: Área contínua de memória para variáveis locais.
- Os valores têm tamanhos fixos conhecidos em tempo de compilação.
- Extremamente rápida: basta mover um ponteiro de pilha.
- Fácil de gerenciar: segue chamadas de função.
- Ótima localidade de memória.
-
Heap: Armazenamento de valores fora das chamadas de função.
- Valores possuem tamanhos dinâmicos determinados em tempo de execução.
- Ligeiramente mais devagar que a pilha: é necessário um pouco de gerenciamento.
- Sem garantias de localidade de memória.
Exemplo
A criação de uma String coloca metadados de tamanho fixo na pilha e dados dinamicamente dimensionados - a string propriamente dita - no heap:
fn main() {
let s1 = String::from("Olá");
}
-
Mencione que uma
Stringé suportada por umVec, portanto ela tem um tamanho e capacidade e pode crescer se for mutável por meio de realocação no heap. -
Se os alunos perguntarem sobre isso, você pode mencionar que a memória subjacente é alocada no heap usando o System Allocator e os alocadores personalizados podem ser implementados usando a API Allocator.
Mais para Explorar
Podemos inspecionar o layout da memória com Rust inseguro (unsafe). No entanto, você deve apontar que isso é legitimamente inseguro!
fn main() {
let mut s1 = String::from("Olá");
s1.push(' ');
s1.push_str("mundo");
// NÃO FAÇA ISSO EM CASA! Somente com propósito educacional.
// String não fornece nenhuma garantia sobre o seu layout, então isso pode causar
// um comportamento indefinido.
unsafe {
let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1);
println!("capacidade = {capacity}, ptr = {ptr:#x}, compr = {len}");
}
}