邁向 Rust

drop 與自動清理(drop and automatic cleanup)

在 C 裡,每個 malloc 都必須剛好對上一個 free,而你親手把那個 free 放到正確的位置——在正常路徑上容易忘記,在提早返回的錯誤路徑上更是極易漏掉。Rust 把這個義務從你手上拿走。當一個擁有資源的值離開範圍——它所在的區塊結束時——Rust 會自動執行它的清理。這個自動清理叫做 drop,規則很簡單:值的擁有者抵達它範圍的結尾,就是釋放這個值所持有之物的暗號。

具體來說,當一個擁有資源的變數離開範圍時,Rust 替你插入清理。對 String 或 Vec<T>,drop 釋放這個值所擁有的堆積記憶體;對檔案控制代碼,drop 關閉檔案;對鎖的守衛,drop 釋放鎖。你不寫 free,通常也不寫 drop——編譯器在擁有者死去的那個收尾大括號處發出這個呼叫,順序與宣告相反。因為所有權保證剛好一個擁有者,drop 對每個值剛好執行一次、在剛好一個定義明確的時刻,所以沒有重複釋放、也沒有什麼好忘記的。這是 C++ 程式設計師稱為 RAII 那個模式的 Rust 形式——把一個資源的釋放綁到擁有它的物件的生命週期上。

為何重要:drop 是讓所有權在實務上得到回報的機制。它正是讓 Rust 能在沒有垃圾回收暫停你程式的情況下,承諾「不會因為忘記釋放而洩漏」與「不會釋放後使用」的東西——清理發生在一個精確、可預測、你能推理的點上,也就是擁有者範圍結束的那一刻,在編譯期就決定了。誠實的提醒值得記清楚。drop 是依範圍執行、而非靠魔法,所以一個被留存得比你本意更久的值(例如被存進一個長壽的結構裡)會比你預期更晚才釋放。而且 Rust 仍然不阻止你故意洩漏——你可以刻意讓某樣東西永遠活著、或呼叫 std::mem::forget——所以 drop 防的是意外的洩漏,而非所有的洩漏。

{ let s = String::from("data"); // 擁有堆積位元組 let v = vec![1, 2, 3]; // 擁有堆積位元組 // ... 使用 s 與 v ... } // 範圍結束:先 drop v,再 drop s(相反順序),記憶體釋放 // 任何地方都沒有寫 free()

清理綁定到擁有者的範圍;drop 在收尾大括號處自動執行。

drop 在擁有者範圍結束時自動執行一次——這正是防止「忘記而洩漏」與「重複釋放」的東西。它不防止「故意洩漏」:一個被永遠留存的值,或 std::mem::forget,永遠不會 drop。

又稱
DropRAII in Rustautomatic free析構自動釋放