C++ 프로그래밍

C++ unique_ptr을 응용하여 자동으로 핸들을 닫는 클래스 만들기

하늘흐늘 2024. 4. 15. 19:38
반응형

C++을 사용하여 프로그램을 하다보면 핸들을 많이 다루게 됩니다. 특히 I/O 관련 작업을 할 때나 윈도우 API를 사용할 때 파일을 비롯한 각종 핸들(HANDLE)을 사용하게 됩니다. 이 때 다 사용한 핸들을 닫아주지 않으면 핸들 관련 누수(Leak)가 생기게 됩니다.

이럴 경우 unique_ptr을 이용하여 구간에서만 핸들을 사용하고 다 사용한 후에는 자동으로 핸들을 자동으로 닫게하면 위에서 말한 문제가 일어날 가능성이 적어지게 됩니다.

아래 예제 코드를 살펴보겠습니다.

#include <iostream>
#include <cstdio>


using namespace std;

struct FileCloser {
	void operator()(FILE* file) const {
		if (file) {
			fclose(file);
			std::cout << "File closed.\n";
		}
	}
};

typedef std::unique_ptr<FILE, FileCloser> ScopeHandle;

int main(int argc, char* argv[])
{
	FILE* file = nullptr;
	fopen_s(&file, "test.txt", "w");
	if (!file) {
		std::cerr << "Failed to open file.\n";
		return 1;
	}

	ScopeHandle filePtr(file);

	fprintf(filePtr.get(), "Hello, world!\n");

	// 파일 핸들이 범위를 벗어나면 자동으로 닫힘

	return 0;
}

실행 결과는 아래와 같습니다.

File closed.

소스 코드는 간단한 예제를 위하여 C 라이브러리의 FILE을 예제로 보여주었습니다. 예제에서 unique_ptr을 사용하여 ScopeHandle을 정의하여 사용하였습니다. unique_ptr에 템플릿 인자 2 개 주는 것이 조금 어색해 보일 수 있는데 2번째 인자는 해당 객체에 대한 삭제자(delete)라고 보시면 됩니다. 삭제자는 리소스 해제 과정의 커스터마이징에 사용된다고 보시면 됩니다. 이 예제에서는 operator()(File* file)가 unique_ptr이 가지고 있는 객체의 포인터를 파라메터로 하여 호출된다고 보시면 됩니다.
예제 코드에서 file에 대한 핸들을 ScopeHandle가 관리하게 하여 함수가 끝나면 자동으로 파일을 close하게 만들었습니다.

예제에서는 C 라이브러리의 FILE을 이용하였지만 조금만 수정하면 윈도우 API의 각종 HANDLE에 대해서도 응용할 수 있습니다.

반응형