Cosa ha Rust invece di un garbage collector?


95

Capisco che Rust non abbia un garbage collector e mi chiedo come viene liberata la memoria quando un binding esce dall'ambito.

Quindi in questo esempio, capisco che Rust recupera la memoria assegnata a "a" quando esce dall'ambito.

{
    let a = 4
}

Il problema che sto avendo con questo, è in primo luogo come questo accade, e in secondo luogo non è una sorta di garbage collection? In cosa differisce dalla "tipica" raccolta dei rifiuti?


12
"Durata deterministica degli oggetti". Simile a C ++.
user2864740

@ user2864740 Quella guida è decisamente obsoleta. La sostituzione moderna sarebbe probabilmente doc.rust-lang.org/book/references-and-borrowing.html .
Veedrac

Risposte:


74

La garbage collection viene in genere utilizzata periodicamente o su richiesta, ad esempio se l'heap è vicino al pieno o al di sopra di una certa soglia. Quindi cerca le variabili inutilizzate e libera la loro memoria, a seconda dell'algoritmo .

Rust saprebbe quando la variabile esce dall'ambito o la sua durata termina al momento della compilazione e quindi inserisce le corrispondenti istruzioni LLVM / assembly per liberare la memoria.

Rust consente anche una sorta di garbage collection, come il conteggio dei riferimenti atomici .


Allocando memoria quando si introducono variabili e liberando memoria quando la memoria non è più necessaria? Non so davvero cosa vuoi dire con questo. Forse abbiamo opinioni diverse su cosa sia un GC.
Ayonix

1
La sua domanda è come l'approccio di Rust differisca da un tipico GC. Quindi ho spiegato cos'è un GC e come lo fa Rust senza un GC.
Ayonix

1
doc.rust-lang.org/book/the-stack-and-the-heap.html lo spiega abbastanza bene. Sì, molte cose sono in pila ma figuriamoci non è un indicatore sufficiente (vedi riquadro). L'ho lasciato fuori per semplicità, poiché la domanda era generalmente posta
Ayonix

1
@Amomum In realtà Rust non ha alcuna new()funzione unta come C, sono solo funzioni statiche, e in particolare qualcosa come let x = MyStruct::new()crea il suo oggetto sullo stack. Il vero indicatore dell'allocazione dell'heap è Box::new()(o una qualsiasi delle strutture che dipendono da Box).
Mario Carneiro

1
Quali altri linguaggi gestiscono la gestione della memoria in modo simile a Rust?
still_dreaming_1

43

L'idea di base della gestione delle risorse (inclusa la memoria) in un programma, qualunque sia la strategia, è che le risorse legate ad "oggetti" irraggiungibili possono essere recuperate. Oltre alla memoria, queste risorse possono essere blocchi mutex, handle di file, socket, connessioni al database ...

Le lingue con un garbage collector analizzano periodicamente la memoria (in un modo o nell'altro) per trovare oggetti inutilizzati, rilasciare le risorse ad essi associate e infine rilasciare la memoria utilizzata da quegli oggetti.

Rust non ha un GC, come gestisce?

Rust ha la proprietà. Utilizzando un sistema di tipo affine , tiene traccia di quale variabile sta ancora trattenendo un oggetto e, quando tale variabile esce dall'ambito, chiama il suo distruttore. Puoi vedere il sistema di tipi affini in vigore abbastanza facilmente:

fn main() {
    let s: String = "Hello, World!".into();
    let t = s;
    println!("{}", s);
}

Rendimenti:

<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;
                     ^

il che illustra perfettamente che in qualsiasi momento, a livello di lingua, la proprietà viene tracciata.

Questa proprietà funziona in modo ricorsivo: se si dispone di un Vec<String>(ovvero, un array dinamico di stringhe), ciascuna Stringè di proprietà del Vecquale a sua volta è di proprietà di una variabile o di un altro oggetto, ecc ... quindi, quando una variabile esce dall'ambito, libera ricorsivamente tutte le risorse che aveva, anche indirettamente. In questo caso Vec<String>significa:

  1. Rilascio del buffer di memoria associato a ciascuno String
  2. Rilascio del buffer di memoria associato allo Vecstesso

Pertanto, grazie al rilevamento della proprietà, la durata di TUTTI gli oggetti del programma è strettamente legata a una (o più) variabili di funzione, che alla fine usciranno dall'ambito (quando il blocco a cui appartengono termina).

Nota: questo è un po 'ottimistico, utilizzando il conteggio dei riferimenti ( Rco Arc) è possibile formare cicli di riferimenti e quindi causare perdite di memoria, nel qual caso le risorse legate al ciclo potrebbero non essere mai rilasciate.


2
"Le lingue con un Garbage Collector analizzano periodicamente la memoria (in un modo o nell'altro)". Molti lo fanno, ma in generale non è vero. I garbage collector in tempo reale eseguono la scansione in modo incrementale anziché periodico. I linguaggi per il conteggio dei riferimenti come Mathematica non eseguono la scansione.
JD

@ JonHarrop: non considero il conteggio dei riferimenti come un meccanismo completo di Garbage Collection poiché deve essere integrato per evitare perdite di cicli. Per quanto riguarda la differenza incrementale / periodica, potrebbe essere la mia scarsa padronanza dell'inglese, ma non riesco a vedere come periodica non copra il caso incrementale ... Penso che il bit "(in un modo o nell'altro)" trasmetta adeguatamente tante varietà esistono approcci. In ogni caso, se hai un modo migliore per descrivere succintamente la Garbage Collection, suggeriscilo. Non ho, tuttavia, intenzione di lanciarmi in una spiegazione completa: non ne sono qualificato.
Matthieu M.

1
"Non considero il conteggio dei riferimenti come un meccanismo completo di Garbage Collection poiché deve essere integrato per evitare perdite di cicli". La RC è convenzionalmente considerata una forma di GC. In Mathematica ed Erlang, ad esempio, i cicli non possono essere creati per progettazione, quindi RC non perde. Per una prospettiva di alto livello, vedere "Una teoria unificata della raccolta dei rifiuti" cs.virginia.edu/~cs415/reading/bacon-garbage.pdf
JD

@ JonHarrop: Vero, se nessun ciclo è possibile, RC non può perdere.
Matthieu M.

2
"Non vedo come periodico non copra il caso incrementale". Gli algoritmi di Stop the world sarebbero considerati periodici mentre la marcatura tricolore è considerata incrementale, ad esempio. Sono opposti in questo contesto.
JD

6

Con un linguaggio in cui è necessario gestire manualmente la memoria, la distinzione tra stack e heap diventa fondamentale. Ogni volta che chiamate una funzione, nello stack viene allocato uno spazio sufficiente per tutte le variabili contenute nell'ambito di tale funzione. Quando la funzione ritorna, lo stack frame associato a quella funzione viene "estratto" dallo stack e la memoria viene liberata per un utilizzo futuro.

Da un punto di vista pratico, questa pulizia involontaria della memoria viene utilizzata come mezzo di memorizzazione automatica della memoria che verrà cancellata al termine dell'ambito della funzione.

Ulteriori informazioni sono disponibili qui: https://doc.rust-lang.org/book/the-stack-and-the-heap.html


3
Sebbene l'utilizzo dello stack sia pratico, le durate deterministiche degli oggetti possono ancora essere gestite se tutti i valori fossero "creati sull'heap". Quindi è un dettaglio di implementazione; non necessariamente una strategia linguistica.
user2864740

2
Continui a usare quella parola. Non credo che significhi quello che pensi significhi.
Svizzera

Significa ciò che desidero esprimere ; essendo l'opposto di vite non deterministiche. Fai un'offerta per una frase migliore.
user2864740

Grazie per la risposta, ho assegnato i punti al primo semplicemente perché è stato inviato per primo. Le informazioni sono altrettanto utili e valide.
rix

@ user2864740 La durata deterministica degli oggetti si riferisce alla capacità di dire esattamente quando la memoria dell'oggetto verrà cancellata una volta chiamato il suo distruttore. Non ha nulla a che fare con il modo in cui viene chiamato quel distruttore in primo luogo. Continui a tirare in ballo lo stesso termine ripetutamente anche se non ha un significato diretto per la domanda.
Svizzera
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.