ps4 - rust traduccion
¿Qué tiene Rust en lugar de un recolector de basura? (3)
Con un lenguaje en el que debe administrar la memoria manualmente, la distinción entre la pila y el montón se vuelve crítica. Cada vez que llama a una función, se asigna suficiente espacio en la pila para todas las variables contenidas dentro del alcance de esa función. Cuando la función regresa, el marco de la pila asociado con esa función se "saca" de la pila, y la memoria se libera para uso futuro.
Desde un punto de vista práctico, esta limpieza inadvertida de memoria se utiliza como un medio de almacenamiento automático de memoria que se borrará al final del alcance de la función.
Hay más información disponible aquí: doc.rust-lang.org/book/the-stack-and-the-heap.html
Entiendo que Rust no tiene un recolector de basura y me pregunto cómo se libera la memoria cuando un enlace queda fuera de alcance.
Entonces, en este ejemplo, entiendo que Rust recupera la memoria asignada a ''a'' cuando sale del alcance.
{
let a = 4
}
El problema que tengo con esto, en primer lugar, es cómo sucede esto, y en segundo lugar, ¿no es esto una especie de recolección de basura? ¿En qué se diferencia de la recolección de basura ''típica''?
La idea básica de administrar recursos (incluida la memoria) en un programa, sea cual sea la estrategia, es que los recursos vinculados a "objetos" inalcanzables pueden recuperarse. Más allá de la memoria, esos recursos pueden ser bloqueos mutex, identificadores de archivos, sockets, conexiones de bases de datos ...
Los idiomas con un recolector de basura escanean periódicamente la memoria (de una forma u otra) para encontrar objetos no utilizados, liberan los recursos asociados con ellos y finalmente liberan la memoria utilizada por esos objetos.
Rust no tiene un GC, ¿cómo se gestiona?
Rust tiene propiedad. Usando un sistema de tipo afín , rastrea qué variable aún se mantiene en un objeto y, cuando dicha variable sale del alcance, llama a su destructor. Puede ver el sistema de tipos afines en efecto con bastante facilidad:
fn main() {
let s: String = "Hello, World!".into();
let t = s;
println!("{}", s);
}
Rendimientos:
<anon>:4:24: 4:25 error: use of moved value: `s` [E0382]
<anon>:4 println!("{}", s);
<anon>:3:13: 3:14 note: `s` moved here because it has type `collections::string::String`, which is moved by default
<anon>:3 let t = s;
^
lo que ilustra perfectamente que en cualquier momento, a nivel de idioma, se rastrea la propiedad.
Esta propiedad funciona de forma recursiva: si tiene un
Vec<String>
(es decir, una matriz dinámica de cadenas), entonces cada
String
es propiedad del
Vec
que es propiedad de una variable u otro objeto, etc., por lo tanto, cuando un La variable se sale del alcance, libera recursivamente todos los recursos que tenía, incluso indirectamente.
En el caso de
Vec<String>
esto significa:
-
Liberación del búfer de memoria asociado a cada
String
-
Liberación del búfer de memoria asociado al
Vec
mismo
Por lo tanto, gracias al seguimiento de la propiedad, la vida útil de TODOS los objetos del programa está estrictamente vinculada a una (o varias) variables de función, que finalmente quedarán fuera de alcance (cuando finalice el bloque al que pertenecen).
Nota: esto es un poco optimista, utilizando el recuento de referencias (
Rc
o
Arc
) es posible formar ciclos de referencias y, por lo tanto, causar pérdidas de memoria, en cuyo caso los recursos vinculados al ciclo podrían nunca liberarse.
La recolección de basura generalmente se usa periódicamente o bajo demanda, como si el montón está cerca de estar lleno o por encima de algún umbral. Luego busca variables no utilizadas y libera su memoria, dependiendo del algorithm .
Rust sabría cuándo la variable se sale del alcance o su vida útil finaliza en el momento de la compilación y, por lo tanto, inserte las instrucciones correspondientes de LLVM / ensamblaje para liberar la memoria.
Rust también permite algún tipo de recolección de basura, como el conteo atómico de referencia .