반응형
std::shared_ptr 사용 시 주의사항
C++에서 제공하는 스마트 포인터인 std::shared_ptr을 사용하면 마치 지역변수를 사용하듯이 편하게 포인터를 사용하는 것이 가능하다. 하지만 편한 만큼 잘못 사용하면 찾아내기 힘든 버그를 만들 수 있기 때문에 잘 알고 사용해야 한다.
아래에서 std::shared_ptr 사용 시에 발생할 수 있는 문제 상황에 대해서 알아보자.
문제 발생 코드
class MyClass
{
public:
MyClass() = default;
~MyClass() = default;
int a;
int b;
void Func()
{
std::cout << a << std::endl;
}
};
int main()
{
std::unordered_map<int32_t, std::shared_ptr<MyClass>> myContainer;
// original은 고유하게 유지되어야하기 때문에 복사된다. 참조 횟수 증가
myContainer.emplace(1, std::make_shared<MyClass>());
// 지역 변수로 const auto& 참조 받기
// 중요: 이때 복사가 일어나지 않으므로 참조 횟수는 여전히 1이다.
const auto& iter = myContainer.find(1);
const auto& refClass = iter->second;
std::cout << "[2] 참조 변수 대입 후 참조 횟수: " << refClass.use_count() << std::endl;
std::cout << "refClass 주소: " << &refClass << std::endl;
refClass->Func();
// 원본을 erase하여 메모리 해제
// iter가 가리키던 MyClass 객체는 이 순간 소멸
myContainer.erase(iter);
// 댕글링 포인터 발생!
// refClass는 이미 메모리에서 해제된 객체의 주소를 가리키고 있다.
// 프로그램이 크래시(Crash)가 나거나, 메모리 오염으로 인해 쓰레기 값이 출력될 수 있음.
std::cout << "[4] 댕글링 포인터로 접근 시도:\n";
// null 체크로는 댕글링 포인터가 발생했는지 체크할 수 없음
if (refClass != nullptr)
{
refClass->Func(); // 미정의 동작 (위험!)
}
return 0;
}
문제 발생 이유

문제가 발생한 이유는 무엇인가?
- std::shared_ptr을 참조로 refClass 지역변수 선언
- 참조로 사용하던 와중에 원본이 제거되면서 참조가 가리키던 std::shared_ptr이 이미 사라진 상황
- 해당 상황에서 참조로 접근하면 미정의 동작이 발생(!)
- 실무 환경에서는 std::shared_ptr로 선언되어 있기 때문에 문제가 간헐적으로 발생할 수 있어서 더욱 찾기가 어렵다.
해결 방법
- 차라리 std::shared_ptr을 참조가 아닌 복사하여 사용한다.
- 복사해서 사용하면 해당 스코프에서는 유효하기 때문에 안전하게 사용이 가능하다.
'프로그래밍 > C++' 카테고리의 다른 글
| C++ Static 함수와 Static 변수에 대해서 (1) | 2026.04.18 |
|---|---|
| C++ operator[] 배열 인덱스 연산자 톺아보기 (1) | 2026.04.15 |
| C++ *와 & 연산자 톺아보기 (0) | 2026.03.29 |
| C++ 역참조 연산자와 화살표 연산자에 대해 (0) | 2026.03.29 |
| C++ operator<< 삽입 연산자 톺아보기 (0) | 2026.03.14 |
댓글