C++

RAII, 스마트 포인터

송현호 2024. 10. 2. 17:57

C++에서 가장 흔한 버그 클래스는 new로 메모리를 할당 했을때 Delete가 누락되서 발생하는 메모리 누수라고 한다.

이때 메모리 누수를 방지하기 위해 강조되는 원칙이 Resource Acquisition Is Initialization(RAII)라고 하는데,

개체가 리소스를 소유하고 객체가 스코프를 벗어났을 때 할당된 자원을 반환하도록 하는 것이다.

 

비주얼 스튜디오의 성능 프로파일러를 사용하여 메모리를 반환하지 않았을 메모리 사용량을 체크해보았다.

int main()
{
    for (int i = 0; i < 10000; i++) {
        int* arr = new int[100];
        delete[] arr; // 메모리를 반환함
    }

    printf("Press any key to exit...\n");
    getchar();
}

 

 

 

 

 

 

 

int main()
{
    for (int i = 0; i < 10000; i++) {
        int* arr = new int[100];
        // delete[] arr; // 메모리를 반환하지 않음
    }

    printf("Press any key to exit...\n");
    getchar();
}

 

 

다음과 같이 메모리를 반환하지 않을 경우 arr에 int배열이 메모리에 쌓여 메모리 누수가 일어난다.

 

메모리 누수가 일어나면 프로그램에 악영향을 끼치기 때문에,

C++은 메모리 관리를 위한 솔루션을 제공하는데 이 중 하나가 스마트 포인터이다.

C++ 표준 라이브러리는 std::unique_ptr, std::shared_ptr, std::weak_ptr의 세 가지 스마트 포인터 형식을 제공하는데 std:unique_ptr의 예시를 살펴보자

다음은 마이크로소프트 공식문서에서 가져온 예시이다.

#include <memory>
class widget
{
private:
    std::unique_ptr<int[]> data;
public:
    widget(const int size) { data = std::make_unique<int[]>(size); }
    void do_something() {}
};

void functionUsingWidget() {
    widget w(1000000);  // lifetime automatically tied to enclosing scope
                        // constructs w, including the w.data gadget member
    // ...
    w.do_something();
    // ...
} // automatic destruction and deallocation for w and w.data

 

private에 int형 스마트포인터 배열 data를 정의하고

public에서 widget의 생성자를 호출하여 인수를 받아 data에 int 배열을 할당한다.

 

widget w(1000000)코드로 w의 data함수에 1000000크기 만큼의 int배열이 할당된 후,

w의 주기가 종료되면 자동으로 data에 할당 된 메모리를 제거한다.

'C++' 카테고리의 다른 글

C++ 콘솔 계산기  (0) 2024.10.05
Hello World!  (1) 2024.10.02