1. 메모리 누수
메모리 누수 문제는 C/C++ 프로그래밍 과정에서 발견하거나 해결하기 가장 힘든 작업이다.
원하는 결과를 내도록 프로그램이 실행될수록 메모리 공간을 잡아먹는다면 메모리 누수 현상이 발생한 것이다.
메모리 누수 현상은 할당했던 메모리를 제대로 해제하지 않을 때 발생한다.
new에 대응되는 delete를 빠짐없이 작성하더라도 누수 현상이 발생하는 경우가 있다.
다음 Simple 클래스 코드를 보면 할당한 메모리를 적절히 해제하도록 작성했다.
class Simple
{
private:
int* mIntPtr;
public:
Simple() { mIntPtr = new int(); }
~Simple() { delete mIntPtr; }
void setValue(int value) { *mIntPtr = value; }
};
void doSomething(Simple*& outSimplePtr)
{
outSimplePtr = new Simple(); // 버그! 원본 객체를 삭제하지 않았다.
}
int main()
{
Simple* simplePtr = new Simple(); // Simple 객체 하나를 할당한다.
doSomething(simplePtr);
delete simplePtr; // 두 번째 객체만 해제한다.
return 0;
}
그런데 doSomething()을 보면 outSimplePtr 포인터가 다른 Simple 객체를 가리키도록 변경했는데,
이때 기본에 가리키던 객체를 삭제하지 않아서 메모리 누수가 발생했다.
객체를 가리키고 있던 포인터를 놓치면 그 객체를 삭제할 방법이 없다.
2. 비주얼 C++을 이용한 메모리 누수 탐지 및 수정 방법
마이크로소프트 비주얼 C++을 사용하고 있다면 디버그 라이브러리에서 기본으로 제공하는
메모리 누수 감지 기능을 활용할 수 있다.
기본 설정에 따르면 이 기능을 사용하지 않게 돼 있지만 MFC 프로젝트를 생성할 때는 자동으로 활성화 된다.
MFC가 아닌 다른 프로젝트에서 이 기능을 사용하려면 코드의 첫머리에 다음 세 문장을 추가한다.
#define _CRTDBG_MAP_ALLOC
#include <cstdlib>
#include <crtdbg.h>
반드시 이 순서대로 작성해야 한다. 또한 new 연산자를 다음과 같이 새로 정의한다.
#ifdef _DEBUG
#ifndef DBG_NEW
#define DBG_NEW new (_NORMAL_BLOCK , __FILE__ , __LINE__ )
#define new DBG_NEW
#endif
#endif // _DEBUG
이때 new 연산자를 #ifndef DBG_NEW 구문 안에 정의했다.
따라서 애플리케이션을 디버그 모드로 컴파일해야 새로 정의한 new가 적용된다.
마지막으로 main() 함수의 첫 부분에 다음 문장을 작성한다.
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
그러면 애플리케이션이 종료할 때 비주얼 C++의 CRT 라이브러리는
현재 감지된 모든 메모리 누수 현상을 디버그 콘솔에 출력한다.
이렇게 설정한 상태에서 앞에서 본 메모리 누수 현상이 발생하는 코드를 실행하면
디버그 콘솔에 다음과 같은 메시지가 출력된다.
이 결과를 보면 메모리가 할당됐지만 해제되지 않은 부분이 어느 파일의 어느 줄에 있는지 확실히 알 수 있다.
줄 번호는 파일 이름 뒤에 소괄호로 묶여 있다.
중괄호로 묶인 숫자는 메모리 할당 횟수다.
예를 들어 {74}는 현재 프로그램이 구동한 후 74번째 할당했다는 것을 의미한다.
VC++에서 제공하는 _CrtSetBreakAlloc() 함수를 호출하면 메모리가 할당되는 순간 실행을 중단하고
디버거를 구동하도록 VC__ 디버그 런타일을 설정할 수 있다.
main() 함수의 시작 부분에 다음 문장을 작성하면 메모리를 74번째 할당하는 시점에 디버거를 구동한다.
_CrtSetBreakAlloc(74);
앞에서 본 Simple 클래스 예제에서 메모리 누수 현상이 발생하는 지점은 두 군데다.
하나는 Simple 객체를 삭제하지 않은 30번 줄이고, 다른 하나는 이 객체가 정수를 힙에 할당하는 15번 줄이다.
비주얼 C++ 디버거의 출력 윈도우에서 메모리 누수 현상을 가리키는 항목을 더블 클릭하면 해당 코드로 이동한다.
'💻프로그래밍 내용 정리 > C++17' 카테고리의 다른 글
[C++ 8.2.2-1] 메서드 정의 방법 (0) | 2022.10.03 |
---|---|
[C++ 8.2.1] 클래스 정의 (0) | 2022.10.03 |
[C++ 7.4.3] weak_ptr (0) | 2022.10.03 |
[C++ 7.4.2] shared_ptr (0) | 2022.09.25 |
[C++ 7.4.1] unique_ptr (0) | 2022.09.25 |