En C/C++ y otros lenguajes de bajo nivel, el desarrollador debe gestionar explícitamente la ubicación de los datos en la memoria: en el stack (variables automáticas) o en el heap (asignación a través de malloc/new). En estos lenguajes, a menudo surgen errores de fugas de memoria, doble liberación o el uso de memoria no inicializada o ya liberada. Rust asume la tarea de un control estricto de la memoria mediante un sistema de propiedad, sin utilizar un recolector de basura.
La gestión automática de memoria a través del stack es conveniente, pero está limitada por los tamaños (profundidad del stack). La asignación en el heap requiere una gestión explícita de recursos, lo cual es peligroso: se puede olvidar liberar la memoria o violar los ámbitos de vida de los punteros. Un recolector de basura no siempre es una solución (costos de recursos, pausas imprevisibles). Los errores en la gestión de memoria conducen a fallos y vulnerabilidades.
En Rust, el stack y el heap se diferencian mediante la gestión automática: todos los valores se colocan en el stack por defecto, mientras que para objetos de tamaño dinámico o de larga duración se utiliza el heap a través de punteros inteligentes (por ejemplo, Box<T>, Vec<T>). El sistema de propiedad y préstamos garantiza que después de la transferencia de propiedad o la finalización del ámbito de vida, los recursos se liberen automáticamente. Todo esto garantiza seguridad en tiempo de compilación y ausencia de pausas innecesarias del recolector de basura.
Ejemplo de código:
fn main() { let a = 42; // asignación en stack let b = Box::new(42); // asignación en heap let mut v = Vec::new(); v.push(1); v.push(2); // datos del array en heap }
Características clave:
¿Se puede liberar manualmente (drop) memoria en el stack?
No. La liberación de variables asignadas en el stack ocurre automáticamente al salir del ámbito, hacer drop manualmente es inútil e incluso inapropiado para punteros de stack.
¿La transferencia (move) implica mover a heap?
No. Mover una variable entre propietarios no necesariamente la traslada al heap, solo cambia la propiedad.
¿Garantiza el uso de Box<T> que T siempre estará en el heap?
Sí, Box<T> efectivamente asigna T en el heap, sin embargo, la propiedad y el ámbito de vida todavía se controlan estrictamente.
En el proyecto se utilizan vectores globales (Vec<T>) con una implementación manual de limpieza a través de mem::forget o drop, a veces dejando punteros colgando en memoria liberada.
Ventajas:
Desventajas:
Los objetos se colocan explícitamente a través de Box, la transferencia de datos ocurre según la regla de propiedad, se utilizan punteros inteligentes para colecciones y no se devuelven referencias a variables del stack.
Ventajas:
Desventajas: