포스트

C++) RAII란?

RAII


  • Resource Acqusition is Initialization. 획득한 자원을 초기화 한다
  • C++ 설계 디자인 패턴 중 하나인 키워드
  • 자원을 사용하고자 하는 상황에서, 생성자에서 자원 획득을,
    소멸자에서 자원 해제를 하는 자원 관리용 클래스를 만드는 프로그래밍 패턴

RAII is a C++ programming technique which binds the life cycle of a resource that must be acquired before use to the lifetime of an object.

  • “자원의 생애주기(life cycle, 자원 획득과 자원 해제)를 객체의 생애(lifetime)에 바인딩시키는 기법이다”
    • 자원의 생애주기란,
      C++ 프로그램에서 자원은 동적 메모리, 쓰레드, 소켓, 파일, 뮤텍스, 데이터베이스 커넥션 등등을 의미
    • 이러한 자원을 사용하기 위해서는, 자원을 사용하기 전에 자원을 획득해야 하고,
      자원을 다 사용하면 자원을 해제해야 한다

RAII의 필요성


  • 동적 프로그래밍을 위해 new키워드를 사용해 힙 메모리에서 메모리를 할당받는다
    • 그러나, 실수나 exception 등으로 할당받은 메모리를 해제하지 못하고 메모리 누수가 발생하거나, mutex에서 lock이 발생하는 경우가 있음
  • java, python, C# 과 같은 다른 객체지향 프로그램에서는 런타임이 자원 관리를 돕지만,
    C++ 에서는 자동 자원 관리를 해주지 않아, 실력에 의해 메모리 문제가 좌우됨!
  • 이러한 문제들을 안전하게 관리하고자 만든것들이 RAII
    • 객체의 생애는 런타임이 알아서 관리해주기때문에, 이에 맡기는 방법
    • 객체의 생성자가 호출될 때 자원을 획득하고,
      객체의 소멸자가 호출될 때 자원을 해제한다
      • exception이 발생하는 경우에도 소멸자는 항상 실행되기 때문에 보장됨
  • unique_ptr, shared_ptr, lock_guard
  • 해당 클래스들은 함수가 끝나면, {}중괄호에서 벗어난다면 소멸자를 호출하여
    ...finally처럼 무조건 실행함

    예시


    RAII를 적용하지 않은 모델

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>

using namespace std;

bool error() {
	return true;
}

void fnc() {
	int* c  = new int[100];
	// std::unique_ptr<int> q(c);
	if (error()) return;    //알수 없는 error발생!!
	delete[] c;    //안써도 알아서 할당 해제를 해준다.
}

int main() {
	fnc();
	printf("hi");
	_CrtDumpMemoryLeaks();
	return 0;
}
  • fnc함수에서 new 를 통해 메모리를 할당받음
  • 그러나 에러가 발생해서 delete[] c;를 호출하지 못하고 중도에 리턴함
  • 메모리 해제가 되지 않아 메모리 누수가 발생함

RAII를 적용한 모델

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>

using namespace std;

bool error() {
	return true;
}

void fnc() {
	int* c  = new int[100];
	std::unique_ptr<int> q(c);
	if (error()) return;    //알수 없는 error발생!!
	delete[] c;    //안써도 알아서 할당 해제를 해준다.
}

int main() {
	fnc();
	printf("hi");
	_CrtDumpMemoryLeaks();
	return 0;
}
  • unique_ptr<int>로 RAII를 적용함
  • 중도에 에러가 발생하여 명시적으로 메모리 반납을 하는 delete[] c; 를 거치지 않아도,
    소멸자가 자동으로 호출되면서 메모리를 반환한다

참조 # C++) RAII란? RAII 개념과 필요성

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.