C++ 동적 할당 new / delete 사용시 주의점
C++은 메모리 관리가 상당히 까다로운 언어입니다.
사용자가 메모리의 동적 할당과 해제를 할 책임이 있기 때문입니다.
조금만 실수하면 메모리 누수나, 메모리 접근 위반으로 프로그램이 강제 종료됩니다.
메모리 누수란 프로그램이 종료되기 전에 할당한 모든 메모리가해제가 되어야 하는데
할당된 메모리가 해제가 되지 않을 때 발생하는 문제입니다.
메모리 접근 위반은 초기화되지 않은 포인터 혹은 할당된 범위 밖을 호출할 때 발생합니다.
초기화되지 않은 포인터는 어떻게 작동할 지 예측을 할 수 없습니다.
대부분의 경우는 프로그램이 강제 종료됩니다.
new 사용하여 메모리를 동적 할당할 시에 주의할 점은 다음과 같습니다.
new는 delete로 해제하고, new[]는 delete[]로 해제해줘야 한다는 것입니다.
간단한 규칙으로 보이지만 신경쓰지 않고 사용하다가 잘못 사용되는 경우가 생깁니다.
이럴 경우 디버깅에 오랜 시간을 투자해야 할 수도 있기 때문에 꼭 다시 한 번 상기하시기 바랍니다.
Effective C++에서는 다음 그림을 들어서 new를 delete[]로 해제했을 때나
new[]를 delete로 해제했을 때의 위험성을 설명합니다.
한 개의 객체를 동적 할당할 때와 객체의 배열로 동적 할당할 때의 구조가 다르다는 의미입니다.
그렇기 때문에 정상적으로 메모리의 해제가 이루어지지 않을 수 있다는 것입니다.
실제 코드를 통해서 알아보도록 하겠습니다.
console project에서 확인하기 위해서 다음과 같은 코드를 추가합니다.
#define _CRTDBG_MAP_ALLOC #include <crtdbg.h>
#include <crtdbg.h>를 하기 이전에 #define _CRTDBG_MAP_ALLOC이 선언되어야 합니다.
#include <iostream> #define _CRTDBG_MAP_ALLOC #include <crtdbg.h> using namespace std; int main() { char* pC = new char[10]; _CrtDumpMemoryLeaks(); delete[] pC; _CrtDumpMemoryLeaks(); return 0; }
Visual Studio 환경에서 F10을 누르면 각 라인 별로 디버깅이 가능합니다.
delete[]를 호출하기 이전의 _CrtDumpMemoryLeaks()에서 메모리 누수(Memory Leak)가 탐지됩니다.
계속 F10으로 메모리를 해제하고 다시 _CrtDumpMemoryLeaks()가 호출되면 아무 것도 표시되지 않습니다.
delete[]로 메모리가 정상적으로 해제되었기 때문입니다.
다만 delete[]를 delete로 변경했을 때는 정상적으로 메모리 누수를 탐지하지 못합니다.
그렇기 때문에 항상 조심해서 코드를 작성해야 합니다.