Tradicionalmente, los Lenguajes se han dividido en dos grandes categorías:
- Control total a través de la gestión manual de la memoria: C, C++, Pascal, …
- Seguridad total a través de la gestión automática de la memoria en tiempo de ejecución: Java, Python, Go, Haskell, …
Rust ofrece una nueva mezcla:
Control total y seguridad a través de la aplicación en tiempo de compilación de la gestión correcta de la memoria.
Lo hace con un concepto de propiedad explícito.
Primero, actualicemos cómo funciona la administración de memoria.
Stack:
- Área continua de memoria para variables locales.
- Los valores tienen tamaños fijos conocidos en tiempo de compilación.
- Extremadamente rápido: simplemente mueva un puntero de pila.
- Fácil de administrar: sigue las llamadas de función.
- Gran recuerdo localidad.
Heap o monticulo :
- almacenamiento de valores fuera de las llamadas a funciones.
- Los valores tienen tamaños dinámicos determinados en tiempo de ejecución.
- Ligeramente más lento que la pila: se necesita algo de contabilidad.
- No hay garantía de localidad de memoria.
Si no se hace con cuidado, esto puede provocar bloqueos, errores, vulnerabilidades de seguridad y pérdidas de memoria.
Ejemplo C, debe llamar a free cada vez que asigno un puntero con malloc:
void foo(size_t n) {
int* int_array = malloc(n * sizeof(int));
//
// ... lots of code
//
free(int_array);
}
Al envolver un puntero en un objeto, puede liberar memoria cuando se destruye el objeto. El compilador garantiza que esto suceda, incluso si se genera una excepción.
Esto a menudo se denomina adquisición de recursos es inicialización (RAII) y le brinda indicadores inteligentes.
Un ejemplo de C++
void say_hello(std::unique_ptr<Person> person) {
std::cout << "Hello " << person->name << std::endl;
}
- El objeto std::unique_ptr se asigna en la pila y apunta a la memoria asignada en el heap.
- Al final de say_hello, se ejecutará el destructor std::unique_ptr.
- El destructor libera el objeto Person al que apunta.
Una alternativa a la gestión de memoria manual y basada en el ámbito es la gestión de memoria automática:
- El programador nunca asigna o desasigna memoria explícitamente.
- Un recolector de basura encuentra memoria no utilizada y la desasigna para el programador.
- Seguro y correcto como Java, pero sin un recolector de basura.
- Según la abstracción (o combinación de abstracciones) que elija, puede ser un único puntero único, referencia contada o atómicamente referencia contada.
- Basado en el alcance como C++, pero el compilador impone una adherencia total.
- Un usuario de Rust puede elegir la abstracción correcta para la situación, algunos incluso no tienen costo en tiempo de ejecución como C.