לדלג לתוכן

1.6 - חיי ערך השמדה וניקוי תחת כשל - פתרון

פתרון סדרי חיים לפי תחומים

המשאב הזמני חי רק בתוך הבלוק הפנימי. שאר המשאבים המקומיים מושמדים כאשר עוזבים את הפונקציה, גם בעקבות החזרת שגיאה.

struct Resource(&'static str);

impl Drop for Resource {
    fn drop(&mut self) {
        println!("drop {}", self.0);
    }
}

fn work(fail_at: u8) -> Result<(), &'static str> {
    let _config = Resource("config");
    if fail_at == 1 {
        return Err("config stage");
    }
    let _input = Resource("input");
    {
        let _temporary = Resource("temporary");
        println!("inner work");
    }
    println!("after inner block");
    if fail_at == 2 {
        return Err("input stage");
    }
    let _output = Resource("output");
    Ok(())
}

fn main() {
    for fail_at in [1, 2, 0] {
        println!("case={fail_at} result={:?}", work(fail_at));
    }
}

במקרה הראשון רק config נרכש ולכן רק הוא מושמד. במקרה השני temporary מושמד בסיום הבלוק, ואחר כך input ו־config בזמן החזרת השגיאה. במקרה המצליח temporary מושמד לפני רכישת output, ובסיום הפונקציה מושמדים output, input ואז config.

ההסבר מתאר יציאה רגילה מתחומים. הריגה חיצונית אינה מבצעת את אותו מעבר בקוד המשתמש. לכן סגירת מתאר אוטומטית יכולה למנוע דליפה במהלך הרצה, אבל אישור שהנתונים נשמרו מחייב פעולה מפורשת ותכנון התאוששות לכשל פתאומי.