반응형
✅ 메모리 누수
할당한 메모리(힙 메모리)를 해제하지 않아서 다시 사용할 수 없는 상태로 남아 있는 것
💥 결과
- 프로그램 종료 전까지 RAM 점유
- 반복되면 메모리 부족, 시스템 느려짐, 크래시 발생
✅ 어떤 경우에 발생하나?
1. delete를 호출하지 않은 경우
void createLeak() {
int* ptr = new int(10);
// delete ptr; ❌ 안 했음
}
ptr
은 지역 변수로 함수 종료 시 사라지지만, new로 할당된 메모리는 남음
2. 포인터가 덮어써질 때
int* ptr = new int(5);
ptr = new int(10); // 이전에 할당한 5는 참조할 방법이 없어짐 ❌ 메모리 누수
3. 예외가 발생했는데 해제를 못했을 때
void risky() {
int* ptr = new int[100];
throw std::runtime_error("Oops!"); // delete[] ptr; 실행되지 않음 ❌
}
4. 소멸자가 호출되지 않은 경우
가장 실무적으로 많이 발생하는 상황 → 가상 소멸자 미사용
class Base {
public:
virtual void run() = 0;
~Base() { std::cout << "Base destroyed\n"; } // ❌ 가상 아님
};
class Derived : public Base {
public:
~Derived() { std::cout << "Derived destroyed\n"; } // 해제 안 됨
};
void func() {
Base* b = new Derived();
delete b; // Base의 소멸자만 호출됨 → Derived 리소스 누수
}
✅ 디버깅하기 어려운 이유
- 프로그램은 정상적으로 실행됨
- 누수가 누적될수록 이상 현상이 발생 (속도 저하, 크래시)
- 누수 위치 추적이 어려움
✅ 해결책
방법 | 설명 |
---|---|
delete 와 delete[] 정확히 사용 |
new → delete / new[] → delete[] |
unique_ptr , shared_ptr 사용 |
RAII 패턴 기반 자동 메모리 관리 |
가상 소멸자 사용 | 다형성 객체 해제 시 자식 소멸자까지 호출 |
예외 안전 코드 | try/catch 또는 스마트 포인터 사용 |
valgrind , ASAN 등 도구 사용 |
리눅스/맥에서는 누수 탐지 도구로 확인 가능 |
✅ 스마트 포인터로 누수 방지 예시
#include <memory>
void safe() {
std::unique_ptr<int> ptr(new int(10)); // 자동 해제
// 또는 auto ptr = std::make_unique<int>(10);
}
✅ 요약
항목 | 요약 |
---|---|
발생 원인 | delete 누락, 포인터 덮어쓰기, 예외 등 |
실전 위험 | 반복되면 성능 저하, 크래시 |
가상 소멸자 | 다형성 기반 해제에서 반드시 필요 |
방지 방법 | 스마트 포인터, RAII, 도구 사용 |
반응형
'언어 > C, C++' 카테고리의 다른 글
Interface vs concept (1) | 2025.06.04 |
---|---|
[c++] concept (0) | 2025.06.03 |
[C++] 인터페이스(Interface) 정리 (0) | 2025.05.31 |
DI(Dependency Injection), DIP(Dependency Inversion Principle) (0) | 2025.05.22 |
c, c++ 임베디드 설계 비교 (1) | 2025.05.21 |
댓글