C API와 unique_ptr을 이용한 리소스 관리 패턴 - 안전한 프로그래밍을 위한 접근법
C API 리소스 관리 패턴
C 언어에서 자주 볼 수 있는 리소스 관리 패턴은 다음과 같다.
- 초기화 함수: 리소스를 할당하고 초기화한다.
- 정리 함수: 할당된 리소스를 해제한다.
- 불투명 포인터(Opaque Pointer): 리소스를 나타내는 포인터로, 사용자는 내부 구조를 알 필요가 없다.
1 |
|
이 패턴에서 확연히 보이는 문제점은 리소스 관리의 책임이 사용자에게 있다는 것이다. 사용자가 resource_cleanup() 을 호출하지 않거나 예외가 발생하는 경우 리소스 누수가 발생한다.
이런 패턴을 보이는 C API들은 꽤 많다. 주로 시스템 프로그래밍, 그래픽스 라이브러리, 데이터베이스 인터페이스 등에서 볼 수 있다. libcurl의 curl_easy_init()/curl_easy_cleanup()이나 SDL의 SDL_CreateWindow()/SDL_DestroyWindow() 같이 짝을 이루는 함수들이 대표적이다.
RAII을 위해 std::unique_ptr 도입
앞에서와 같은 경우에 std::unique_ptr을 사용하면 리소스 관리를 더 안전하고 편리하게 할 수 있다. 커스텀 deleter를 사용해 cleanup 함수를 자동으로 호출할 수 있다.
1 |
|
예제에서 make_resource 와 같이 구현하게 되면 편리하다.
- 포인터와 delete만 전달하게 되어 인터페이스를 간단하게 유지할 수 있다.
- 컴파일러가 T와 Deleter 타입을 자동으로 추론하게 된다.
- Perfect Forwarding을 통해서 deleter를 효율적으로 전달하게 된다.
위의 예제에서는 FILE* 포인터를 관리할 때 편리하다. 파일은 스코프를 벗어날 때 자동으로 닫히게 된다. 이 패턴을 사용해서 RAII(Resource Acquisition Is Initialization) 원칙도 쉽게 따를 수 있다. 리소스 누수를 방지하고 예외 상황 발생에 대한 안정성도 높일 수 있다.
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.