라벨이 RAII인 게시물 표시

[Rust] _는 bind하지 않는다

RustRAII idiom을 사용하는 언어로, 객체가 소멸하는 시점에 따라 코드의 의미가 달라진다. 예를 들어 아래 코드를 보자.이 코드는 Service의 객체를 생성하고 종료하기를 기다리는 코드다. 이 코드는 문법적으로는 아무 문제가 없다. 하지만 종료할 때까지 Service가 어떤 동작을 수행하기를 원했다면 이는 틀린 코드다. Service 객체는 아무 변수에도 bind 되지 않았기 때문에 이 객체는 두 번째 줄에 있는 문장이 끝나면 소멸한다.Service 객체가 wait_for_exit이 수행될 때까지 살아있기를 원한다면, 아래와 같이 변경해야 한다. 위의 코드에서 Service의 객체는 변수 service에 bind 된다. 따라서 두 번째 라인이 끝나도 소멸하지 않고 wait_for_exit이 종료되는 것을 기다리고, run 함수가 종료되면서 stack이 unwind 될 때 소멸한다.하지만 위의 코드를 컴파일하면 server가 unused variable이라는 경고가 보일 것이다. Rust 컴파일러는 선언된 변수가 사용되지 않으면 경고를 내기 때문이다. 그렇다면 사용하지 않는 변수의 소유권만 가지고 있고 싶을 때는 어떻게 해야 할까? 이 경우 _(underscore)로 시작하는 변수 이름을 사용하면 된다. Rust 컴파일러는 _로 시작하는 변수를 특별 취급하기 때문에, _로 시작하는 변수는 사용하지 않아도 컴파일러 경고가 나지 않는다. 그렇다면 사용하지 않는 변수에 아무런 이름을 주지 않으면 어떻게 될까? 어차피 사용하는 것이 목적이 아니고, 객체를 bind만 해서 가지고 있는 것이 목적이라면 아래 코드처럼 아무 이름 없이 _를 변수로 사용해도 되지 않을까?아쉽게도 위 코드는 예상대로 동작하지 않는다. 이는 _가 객체의 소유권을 가지지 않기 때문이다. 이를 Rust의 용어로는 _는 value를 bind 하지 않는다고 말한다. 즉, 위의 코드는 Service 객체를 생성하고 소멸시킨 뒤 wait_for_exit 함수를 실행하는 service_run…

RAII는 무엇인가

RAII는 C++에서 자주 쓰이는 idiom으로 자원의 안전한 사용을 위해 객체가 쓰이는 스코프를 벗어나면 자원을 해제해주는 기법이다. C++에서 heap에 할당된 자원은 명시적으로 해제하지 않으면 해제되지 않지만, stack에 할당된 자원은 자신의 scope가 끝나면 메모리가 해제되며 destructor가 불린다는 원리를 이용한 것이다.
 원래는 exception 등으로 control flow가 예상치 못하게 변경될 때를 대비하기 위해서 쓰이던 기법이다.

 아래의 예제를 보자.

 첫 번째 코드는 위험하다. thisFunctionCanThrowException() 함수에서 exception을 발생시킨다면 resource를 해제하지 못한다.
두 번째 코드는 일단은 resource를 해제하고 있다. 하지만 보기에 좋은 코드는 아니다. 그리고 유지하기도 어려워진다.
세 번째 코드는 RAII를 위해 c++ 11의 스마트 포인터인 unique_ptr을 이용하는 방법이다. unique_ptr은 소멸할 때 자신이 들고 있는 메모리를 해제시켜주기 때문에 함수 밖으로 나가면 resource가 해제되는 것이 보장된다.

 여기서 말하는 자원은 단순히 heap 메모리만을 말하는 것이 아니다. heap 메모리 이외에도 파일이나 db와 같은 것들도 전부 RAII를 이용해 안전하게 사용할 수 있다.
여기에 더 나아가서 특정 scope를 벗어나면 반드시 실행돼야 하는 코드들도 RAII를 이용해 처리할 수 있다. 즉, 다른 언어에서 finally에 해당하는 구문을 RAII를 이용해서 처리할 수 있다. 실제로 C++의 아버지이자 RAII라는 용어를 처음 만든 Bjarne Stroustrub는 c++에 finally를 집어넣지 않는 이유를 "RAII가 있는데 굳이 있을 필요가 없다."라고 말하고 있다.