ProgrammazioneSviluppatore Rust

Che cosa sono i lifetimes in Rust e a cosa servono quando si lavora con i riferimenti?

Supera i colloqui con l'assistente IA Hintsage

Risposta

In Rust, i lifetimes definiscono l'ambito di visibilità dei riferimenti, in modo che il compilatore possa assicurarsi che i puntatori non siano pendenti (non ci sono riferimenti pendenti). Questo garantisce la sicurezza della memoria durante la compilazione senza la necessità di un garbage collector.

Quando lavori con i riferimenti, Rust richiede di specificare esplicitamente il loro lifetime quando il compilatore non può dedurlo da solo. Di solito, questo viene fatto utilizzando la sintassi 'a:

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } }

Qui entrambi i parametri e il valore di ritorno hanno lo stesso lifetime, il che garantisce che il riferimento restituito non viva più a lungo di uno dei argomenti.

I lifetimes non modificano la durata della vita dei dati, ma la descrivono solo al compilatore.

Domanda insidiosa

È possibile restituire un riferimento a una variabile locale all'interno di una funzione?

No, non è possibile: poiché tale variabile verrà distrutta all'uscita dalla funzione. Esempio:

fn foo() -> &String { // errore di compilazione! let s = String::from("hello"); &s } // riferimento a s diventa non valido

Il compilatore non permetterà di compilare tale codice: ti proteggerà dall'uso di riferimenti a dati distrutti.

Esempi di errori reali a causa della mancata conoscenza delle sfumature dell'argomento


Storia

Nel team sono emerse molte perdite di memoria quando le funzioni restituivano accidentalmente riferimenti a buffer locali. Questo ha causato problemi, e solo il compilatore ha salvato la situazione iniziando a lamentarsi sui lifetimes. A causa della frequente comparsa di tali errori, è stata adottata la regola di specificare esplicitamente il lifetime se la funzione lavora con strutture complesse con riferimenti annidati.


Storia

Nel progetto è stato scritto del codice generico per la cache dei dati. Con una progettazione scorretta dei parametri generici lifetime, si è verificato l'errore "cannot infer lifetime" e non è stato possibile dedurre la durata della vita dei dati memorizzati nella cache. Questo ha portato a impostare le annotazioni di lifetime con tentativi ed errori, fino a quando non è stata presa la decisione di separare i dati memorizzati in cache e quelli non memorizzati in cache in strutture diverse.


Storia

Uno dei colleghi ha cercato di implementare un pool di connessioni utilizzando riferimenti agli oggetti delle connessioni, ma non ha considerato che i lifetimes delle connessioni non coincidevano con il lifetime del pool. Di conseguenza, sono emersi riferimenti pendenti dopo il rilascio delle connessioni, che sono stati notati solo durante i test complessivi. Dopo questo, il progetto è passato a wrapper sicuri (Arc<Mutex<T>>).