Zum Inhalt springen

Lebensdauern

Programm 1:

/// Adds a Display-able object into a vector of
/// Display trait objects
use std::fmt::Display;
fn add_displayable<T: Display>(
v: &mut Vec<Box<dyn Display>>,
t: T
) {
v.push(Box::new(t));
}

Wenn Sie versuchen würden, dieses Programm zu kompilieren, welche der folgenden Beschreibungen trifft am besten auf den Compilerfehler zu, den Sie erhalten würden?

Beim Umwandeln von Box<T> in Box<dyn Display> (implizit in v.push(..)) verlangt Rust, dass das Trait-Objekt dyn Display den Vektor überlebt. Die Lebensdauer von T ist jedoch nicht spezifiziert, sodass T möglicherweise nicht lange genug lebt.


Programm 1:

/// Adds a Display-able object into a vector of
/// Display trait objects
use std::fmt::Display;
fn add_displayable<T: Display>(
v: &mut Vec<Box<dyn Display>>,
t: T
) {
v.push(Box::new(t));
}

Normalerweise gibt der Compiler den folgenden Fehler zurück, wenn Sie versuchen, diese Funktion zu kompilieren:

error[E0310]: the parameter type `T` may not live long enough
--> test.rs:6:12
|
6 | v.push(Box::new(t));
| ^^^^^^^^^^^

Nehmen Sie an, dass der Compiler diese Funktion NICHT abgelehnt hat. Welche (falls zutreffend) der folgenden Programme würden (1) den Compiler passieren und (2) bei Ausführung möglicherweise undefiniertes Verhalten verursachen? Markieren Sie jedes Programm, das beide Kriterien erfüllt, ODER markieren Sie „Keines dieser Programme“, wenn keines davon zutrifft.

Dieses Programm ist speicherunsicher. Um eine Verletzung der Speichersicherheit zu erzeugen, muss das Programm einen Typ T erstellen, der Referenzen enthält, die den Vektor nicht überleben. Wenn Sie beispielsweise &n hinzufügen, wobei n den Gültigkeitsbereich vor v verlässt, bedeutet dies, dass die spätere Verwendung von v[0] ein Lesen von freigegebenem Speicher ist.


Programm 1:

/// Adds a Display-able object into a vector of
/// Display trait objects
use std::fmt::Display;
fn add_displayable<T: Display>(
v: &mut Vec<Box<dyn Display>>,
t: T
) {
v.push(Box::new(t));
}

Welche der folgenden Korrekturen (gelb hervorgehoben) erfüllt diese drei Kriterien am besten:

  1. Die korrigierte Funktion wird vom Rust-Compiler akzeptiert,
  2. Die korrigierte Funktion bewahrt die Absicht des ursprünglichen Codes, und
  3. Die korrigierte Funktion führt keine unnötigen Ineffizienzen ein

Die idiomatischste Korrektur besteht darin, zu spezifizieren, wie die Lebensdauer von T mit der Lebensdauer des Trait-Objekts dyn Display zusammenhängen sollte. Hier bedeutet das, einen Lebensdauerparameter 'a hinzuzufügen, der besagt, dass T 'a überlebt und dass die Trait-Objekte ebenfalls mindestens für 'a leben. Die Verwendung einer 'static-Schranke ist dasselbe, aber schlechter: Sie ist einfach weniger ausdrucksstark und verbietet den Trait-Objekten des Vektors, jemals Referenzen zu halten. Das Anbringen der Lebensdauer 'a an die Referenz &'a mut Vec<..> ist nicht korrekt und behebt den Compilerfehler nicht.