[C++] delete[] 연산자는 어떻게 배열을 지울 수 있을까?

Will-Big·2025년 2월 13일
0

Cpp

목록 보기
5/7

Effective C++을 보며 newdelete 연산자에 대해 공부하다 보면, delete[] 연산자가 단순히 포인터를 넘겨주는 것이 아니라 내부에 저장된 배열의 길이(혹은 요소 개수)를 이용해 전체 배열을 올바르게 해제한다는 내용을 접하게 됩니다. 그런데 어떻게 delete[]는 배열의 길이를 알 수 있을까요?

new[]와 delete[]의 내부 동작

C++에서 new[] 연산자로 동적 배열을 할당하면, 컴파일러는 단순히 필요한 메모리 크기만을 할당하는 것이 아니라, 추가적인 메타데이터를 함께 저장합니다.
이 메타데이터에는 일반적으로 배열에 할당된 요소의 개수 또는 배열의 길이와 같은 정보가 포함됩니다.

예를 들어, 아래와 같이 배열을 할당한다고 가정해봅니다.

MyClass* arr = new MyClass[3];

이때 실제로 메모리에는 다음과 같은 구조로 저장될 가능성이 있습니다.

// memory layout
| meta data (len=3) | arr[0] | arr[1] | arr[2] |

이 메타데이터의 위치와 저장 방식은 구현체에 따라 다를 수 있지만, 많은 컴파일러에서 배열의 앞부분에 저장됩니다.

그렇다면 delete[] 연산자는 무엇을 할까요?
delete[] 연산자는 전달받은 포인터를 기준으로, 배열 앞에 숨겨진 메타데이터를 읽어 배열의 길이를 알아내고,
각 요소에 대해 적절히 소멸자(destructor)를 호출한 후 메모리 전체를 해제합니다.

왜 일반 delete로는 안 되는가?

만약 new[]로 할당한 배열에 대해 단순히 delete를 사용하면,
메타데이터에 저장된 배열 길이 정보를 참조하지 않고 단일 객체만 해제하려고 시도하게 됩니다.
이 경우, 다음과 같이 요소의 소멸자가 올바르게 호출되지 않아 정의되지 않은 동작(Undefined Behavior)이 발생할 수 있습니다.

MyClass* arr = new MyClass[3];
delete arr;  // 잘못된 사용: 첫 번째 요소만 소멸자 호출되고 나머지는 무시됨

따라서 동적 배열을 해제할 때는 반드시 delete[] 를 사용해야 합니다.

결론

new[] 연산자: 동적 배열 할당 시 내부에 배열의 길이 등 메타데이터를 함께 저장합니다.
delete[] 연산자: 전달받은 포인터의 앞부분에 저장된 메타데이터를 참조해 배열의 길이를 알아내고,
각 요소의 소멸자를 호출한 후 메모리를 해제합니다.
이 메커니즘은 구현 세부 사항이므로, 프로그래머는 단지 올바른 대응(delete[])을 사용하기만 하면 됩니다.

profile
개발자가 되고싶어요

0개의 댓글