RAII (Resource Acquisition Is Initialization) è un'idioma proveniente da C++, secondo cui la durata di vita di una risorsa è strettamente legata alla durata di vita di un oggetto nello stack. In Rust, questo concetto è alla base del sistema di proprietà e rilascio delle risorse, permettendo di fare a meno dei tradizionali garbage collector (GC).
Molti linguaggi gestiscono la memoria e le risorse tramite un garbage collector, che periodicamente "ripulisce" gli oggetti non necessari. Questa strategia aumenta i ritardi e non garantisce un immediato rilascio delle risorse esterne (file, socket, ecc.). Nella programmazione a basso livello e sistematica, tale situazione è inaccettabile: è necessaria precisione e determinismo nella gestione delle risorse.
In Rust, ogni oggetto possiede la propria risorsa e la rilascia rigorosamente al momento della distruzione (out of scope), tramite la chiamata a Drop (l'analogo del distruttore). Di conseguenza, le risorse vengono rilasciate immediatamente e tutti gli errori di rilascio implicito sono ridotti al minimo. Il sistema di tipi e la proprietà in Rust previene perdite e doppio rilascio quasi in fase di compilazione.
Esempio di codice:
struct FileWrapper { file: std::fs::File, } impl Drop for FileWrapper { fn drop(&mut self) { println!("FileWrapper chiude il file! (uscita dallo scope)"); } } fn main() { let _fw = FileWrapper { file: std::fs::File::create("test.txt").unwrap() }; // All'uscita da main, drop viene garantito }
Caratteristiche principali:
Viene chiamato Drop per i valori che sono stati spostati (moved) precedentemente?
No, dopo lo spostamento del valore, Drop viene chiamato solo per il nuovo proprietario, il vecchio oggetto è considerato "vuoto" e Drop non viene attivato.
let file1 = FileWrapper {...}; let file2 = file1; // file1 move // Drop verrà chiamato una volta — per file2
Una panic! o un unwrap() a metà area di visibilità può ostacolare la chiamata a drop?
No, la panico o l'uscita per errore non annullano la chiamata al distruttore — Drop verrà necessariamente chiamato per tutti gli oggetti usciti dall'area.
Se un riferimento possiede un oggetto, verrà chiamato drop al termine della vita del riferimento?
No, drop viene chiamato solo per il proprietario dell'oggetto, i riferimenti non possiedono. Per le risorse heap, è necessario un puntatore intelligente.
Un sviluppatore ha passato un descrittore di file tramite riferimento a una funzione di scrittura. Dopo la fine del programma, il file ha mantenuto un lock, poiché drop non è stato chiamato (non c'era un proprietario, si utilizzava un riferimento).
Pro:
Contro:
La proprietà delle risorse è sempre stata trasferita tramite strutture che implementano Drop. Tutti i file aperti, le connessioni o i lock vengono rilasciati automaticamente al termine dello scope o in caso di panico. Un lasciapassare per una gestione sicura e triviale delle risorse anche in progetti complessi.
Pro:
Contro: