ProgrammatieRust systems ontwikkelaar

Kan een struct in Rust verwijzingen naar andere objecten bevatten? Wat zijn de beperkingen van de levensduur van dergelijke verwijzingen en wat gebeurt er als je probeert een struct met onvolledige levensduur van verwijzingen uit een functie te retourneren?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

Structs in Rust kunnen verwijzingen naar andere objecten opslaan door expliciete leeftijden (lifetimes) in de struct-definitie aan te geven. Dit is nodig zodat de compiler kan controleren dat geen enkele verwijzing ongeldig wordt. Hier is een voorbeeld:

struct Book<'a> { title: &'a str, author: &'a str, }

Hier bevat de struct Book twee verwijzingen met dezelfde levensduur 'a. Wanneer je een functie schrijft die zo'n struct retourneert, ben je verplicht te garanderen dat alle verwijzingen daarin geldig zijn, ongeacht de interne logica van de functie:

fn book_factory<'a>(title: &'a str, author: &'a str) -> Book<'a> { Book { title, author } }

Als je probeert een struct te retourneren waar verwijzingsvelden bijvoorbeeld naar lokale variabelen van deze functie wijzen, dan zal er een compilatiefout optreden, omdat de levensduur van de verwijzingen niet voldoende is voor veilige toegang.

Misleidende vraag

Kun je een struct maken die in een van zijn velden een verwijzing (&str) bevat, en in een ander veld een String? Waarom kan dit een probleem zijn?

Een veelvoorkomend foutief antwoord: "Ja, dat kan, dat is veilig".

In werkelijkheid, als &str van een String is verkregen, en de struct overleeft deze String, wordt de verwijzing een dangling reference. Bijvoorbeeld:

struct Test<'a> { s1: &'a str, s2: String, } fn main() { let s = String::from("hello"); let t = Test { s1: &s, s2: s }; // t.s1 is eigenlijk alleen veilig zolang s2 (s) leeft, maar als s2 als eerste wordt verwijderd — fout }

Voorbeelden van echte fouten door gebrek aan kennis over de nuances van het onderwerp


Verhaal In een project probeerden ze een struct te retourneren uit een laadfunctie die een verwijzing naar een tijdelijke string bevatte die binnen dezelfde functie was gemaakt. De code kon niet gecompileerd worden, er was aanzienlijke herschrijving nodig om de levensduur van de lokale variabele te verwijderen.


Verhaal Een ontwikkelaar was van plan een struct te gebruiken met een verwijzing naar een array-element dat in de functie was gemaakt, maar na terugkeer bleek deze verwijzing ongeldig te zijn, wat de compiler succesvol voorkwam.


Verhaal In een bedrijfsproject bewaarden ontwikkelaars een &str-verwijzing naar een string van een ander object dat uit de collectie was verwijderd voordat de verwijzing zelf — bij een daaropvolgende toegang tot deze verwijzing veroorzaakte dit een panic.