Smart Pointer

김민서·2025년 11월 14일

C/C++

목록 보기
1/6

C/C++에서 메모리 관리

C/C++은 Java처럼 Garbage Collector가 자동으로 메모리를 관리해주는 언어와는 다르다. 개발자가 직접 메모리를 할당하고 해제해야 하기 때문에, 메모리 관리에 각별한 주의가 필요하다. 예를 들어 C에서는 mallocfree를 사용해 메모리를 확보하고 반환하며, C++에서는 newdelete가 그 역할을 맡는다. 이러한 특징으로 인해 프로그램의 효율성은 높일 수 있지만, 동시에 메모리 누수나 잘못된 해제와 같은 위험 역시 따라온다. 결과적으로, C/C++ 프로그래머는 항상 메모리 사용에 신경을 써야 하며, 이는 두 언어의 중요한 특징 중 하나라고 할 수 있다.

// 1. 메모리 누수
void memoryLeakExample() {
    int* ptr = new int(42);
    // delete 안 함 -> 메모리 누수
}

// 2. 널 포인터 이슈
void nullPointerExample() {
    int* ptr = nullptr;
    *ptr = 10;  // 크래시!
}

// 3. 댕글링 포인터 이슈
void danglingPointerExample() {
    int* ptr = new int(42);
    delete ptr;
    *ptr = 10;  // 이미 해제된 메모리 접근
}

Smart Pointer

C++에서 동적 메모리를 안전하게 관리하기 위해 제공하는 템플릿 클래스

일반 포인터를 래핑하여 RAII(Resource Acquisition Is Initialization) 원칙에 따라 자동으로 메모리를 관리해준다.
Smart Pointer 객체가 생성될 때 메모리를 할당하고, 스코프를 벗어나 소멸자가 호출될 때 자동으로 메모리를 해제한다.
이를 통해 개발자가 명시적으로 delete를 호출하지 않아도 메모리 누수를 방지할 수 있다.

종류

  • Unique Ptr

    • 단독 소유권을 가진다.
    • 복사가 불가능하며, move 연산만 가능하다.
    • 오버헤드가 거의 없어 일반 포인터와 성능이 거의 동일하다.
    void uniquePtrExample() {
        std::unique_ptr<int> ptr1 = std::make_unique<int>(42);
        // std::unique_ptr<int> ptr2 = ptr1;  // 컴파일 에러
        std::unique_ptr<int> ptr2 = std::move(ptr1);  // 이동만 가능
    }
  • Shared Ptr

    • 여러 객체가 하나의 리소스를 공유한다.
    • 내부적으로 Reference Counting을 통해 소유자 수를 추적한다.
    • 마지막 shared_ptr이 소멸될 때 메모리가 해제된다.
    • Reference Counting 관리로 인한 약간의 성능 오버헤드가 있다.
    • Shared Ptr의 순환 참조는 메모리 누수를 발생시킬 수 있으므로, 이런 경우 Weak Ptr을 사용해야 한다.
    void sharedPtrExample() {
        std::shared_ptr<int> ptr1 = std::make_shared<int>(42);
        std::shared_ptr<int> ptr2 = ptr1;  // 복사 가능
        std::cout << ptr1.use_count();  // 2
    }
  • Weak Ptr

    • Shared Ptr과 함께 사용되며, 소유권 없이 객체를 참조만 하는 포인터
    • Reference Counting을 증가시키지 않는다.
    • Shared Ptr 간의 순환 참조 문제를 해결하는 데 사용된다.
    • lock()은 객체가 아직 살아있으면 Shared Ptr을 반환하고, 이미 소멸되었으면 nullptr을 반환한다.
      void weakPtrExample() {
          std::shared_ptr<int> shared = std::make_shared<int>(42);
          std::weak_ptr<int> weak = shared;  // 참조 카운트 증가 안 함
    
          if (auto ptr = weak.lock()) {  // shared_ptr로 변환
              std::cout << *ptr;
          }
      }
profile
시스템 개발 공부 중

0개의 댓글