RAII
Rust의 변수는 스택에 데이터를 저장하는 것 이상의 일을 합니다. 예를 들어 Box<T>는 힙 메모리를 소유하는 것처럼 리소스를 _소유(own)_하기도 합니다. Rust는 RAII (자원의 획득은 초기화이다)를 강제하므로, 객체가 스코프를 벗어날 때마다 소멸자가 호출되어 소유한 리소스가 해제됩니다.
이러한 동작은 리소스 누수 버그를 방지하므로, 수동으로 메모리를 해제하거나 메모리 누수에 대해 걱정할 필요가 없습니다! 간단한 예시를 보여드리겠습니다:
// raii.rs
fn create_box() {
// 힙에 정수를 할당합니다
let _box1 = Box::new(3i32);
// `_box1`은 여기서 파괴되고, 메모리가 해제됩니다
}
fn main() {
// 힙에 정수를 할당합니다
let _box2 = Box::new(5i32);
// 중첩된 스코프:
{
// 힙에 정수를 할당합니다
let _box3 = Box::new(4i32);
// `_box3`은 여기서 파괴되고, 메모리가 해제됩니다
}
// 재미 삼아 많은 상자를 만듭니다
// 수동으로 메모리를 해제할 필요가 없습니다!
for _ in 0u32..1_000 {
create_box();
}
// `_box2`는 여기서 파괴되고, 메모리가 해제됩니다
}
물론 valgrind를 사용하여 메모리 에러를 다시 확인할 수 있습니다:
$ rustc raii.rs && valgrind ./raii
==26873== Memcheck, a memory error detector
==26873== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==26873== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==26873== Command: ./raii
==26873==
==26873==
==26873== HEAP SUMMARY:
==26873== in use at exit: 0 bytes in 0 blocks
==26873== total heap usage: 1,013 allocs, 1,013 frees, 8,696 bytes allocated
==26873==
==26873== All heap blocks were freed -- no leaks are possible
==26873==
==26873== For counts of detected and suppressed errors, rerun with: -v
==26873== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
누수가 없습니다!
소멸자
Rust에서 소멸자의 개념은 Drop 트레이트를 통해 제공됩니다. 소멸자는 리소스가 스코프를 벗어날 때 호출됩니다. 모든 타입에 대해 이 트레이트를 구현할 필요는 없으며, 자체적인 소멸자 로직이 필요한 경우에만 구현하면 됩니다.
아래 예제를 실행하여 Drop 트레이트가 어떻게 작동하는지 확인해 보세요. main 함수의 변수가 스코프를 벗어나면 사용자 정의 소멸자가 호출될 것입니다.
struct ToDrop;
impl Drop for ToDrop {
fn drop(&mut self) {
println!("ToDrop이 드롭되고 있습니다");
}
}
fn main() {
let x = ToDrop;
println!("ToDrop을 만들었습니다!");
}