Revisión de la memoria de programas
Los programas asignan memoria de dos formas:
-
Stack: Zona de memoria continua para las variables locales.
- Los valores tienen tamaños fijos conocidos en tiempo de compilación.
- Muy rápida: mueve el stack pointer.
- Fácil de gestionar: sigue las llamadas de funciones.
- Excelente localidad de memoria.
-
Heap: almacenamiento de valores fuera de las llamadas de funciones.
- Los valores tienen tamaños dinámicos determinados en runtime.
- Ligeramente más lento que el stack: requiere cierta trazabilidad.
- No se puede asegurar la localidad de la memoria.
Ejemplo
Al crear un String
, los metadatos de tamaño fijo se colocan en la stack y los datos de tamaño dinámico (la cadena real) en el heap:
fn main() { let s1 = String::from("Hola"); }
-
Menciona que un
String
está respaldado por unVec
, por lo que tiene capacidad y longitud y, si es mutable, puede crecer mediante reasignación en el heap. -
Si los alumnos lo preguntan, puedes mencionar que la memoria subyacente recibe una asignación de heap mediante el Asignador del Sistema y que se pueden implementar asignadores personalizados mediante el Allocator API.
Más información
We can inspect the memory layout with unsafe
Rust. However, you should point out that this is rightfully unsafe!
fn main() { let mut s1 = String::from("Hola"); s1.push(' '); s1.push_str("mundo"); // ¡NO HAGÁIS ESTO EN CASA! Solo con fines educativos. // La cadena no proporciona garantías sobre su diseño, por lo que podría desencadenar // un comportamiento indefinido. unsafe { let (ptr, capacity, len): (usize, usize, usize) = std::mem::transmute(s1); println!("ptr = {ptr:#x}, longitud = {len}, capacidad = {capacity}"); } }