이 포스팅에서는 동적할당에 대해 배워보겠습니다.
동적할당은 일반적인 변수를 만드는 것과는 큰 차이가 존재합니다.
그러면 지금부터 알아보겠습니다.
1) 동적할당이란?
컴퓨터의 메모리는 간단하게 위와 같이 동작합니다.
그리고 이번에 알아볼 동적할당은 힙 영역이라는 공간을 사용합니다.
이 힙 영역은 일반적인 방식으로 사용할 수 없고,
운영체제를 통해 힙 영역에 설계자가 요구한 만큼의 공간을 할당받는 식으로 작동합니다.
2) 동적할당의 장단점
장점으로는,
정해진 공간에서 정해진 위치만 사용하게 되므로 다른 요소들끼리 겹치거나 부딪힐 이유가 없다는 것입니다.
또한 정해진 공간만 사용한다는 점에서 메모리의 낭비도 줄일 수 있게 됩니다.
단점으로는,
이렇게 사용한 힙 영역에 대한 관리를 설계자가 직접해주어야 한다는 것입니다.
크게 와닿지 않을 수 있지만, 이 문제야말로 동적할당의 가장 큰 위험이 됩니다.
한번 보도록 하겠습니다.
3) 동적할당의 사용
(1) delete를 생략하게 되는 경우
위와 같이 동적할당이 이루어진 이후, delete를 하지 않게 되면 동적할당된 메모리를 계속 점유하게 됩니다.
이는 heap의 공간을 계속 줄어들게 하여 결국 메모리 누수를 발생시켜 크래시를 일으키게 됩니다.
(2) delete 이후의 문제
이번에는 제대로 delete를 했지만, delete 이후의 heap 메모리에 접근을 하게 되었습니다.
결과는 어떻게 나올까요?
아무런 문제가 발생하지 않았습니다!
하지만 디버그 모드에서 확인해보면
위와 같은 에러 메세지와 함께 메모리를 읽어들일 수 없는 것을 확인할 수 있습니다.
디버깅과는 달리 실행을 했을 때 왜 문제없이 실행할 수 있었을까요?
그 이유는 운영체제가 동적할당을 실제 설계자가 요구한 정량이상으로 더한다는 것입니다.
상황마다 요구한 정량만큼의 메모리를 할당하고 삭제하는 것은 운영체에게 있어 작업을 매우 더디게 만들 것입니다.
따라서 운영체제는 정량이상의 힙 영역을 동적할당하고, 삭제해도 완전히 소멸시키지 않고
다음에 이루어질 동적할당을 위해 해당 영역을 사용하지는 않되 들고만 있게 됩니다.
그리고 이 부분에서 문제가 발생합니다.
이러한 문제는 발생한 위치가 어디인지 찾기도 힘든 경우가 많습니다.
이런 문제를 Use-After-Free 라고 부릅니다.
(3) 동적할당한 요소를 들고 있는 경우
클래스가 위와 같이 수정되었다고 가정해보겠습니다.
메인 코드도 다음과 같이 수정되었습니다.
역시 실행 자체는 문제없이 가능하지만,
delete이전에는 문제없이 동작하던 포인터가
다음과 같이 변경되었음을 알 수 있습니다.
위와 같이 제대로 관리되지 못하는 동적할당은 메모리에 직접적인 타격을 줄 수 있으므로 조심하여야 합니다.
4) 동적할당의 안전한 사용
해제한 이후에는 기존의 참조를 nullptr로 밀어주고, nullptr로 만든 이후에도 발생할 수 있는 문제를 피하고자
조건문을 걸어 사용하지 않는 방식으로 접근하였습니다.
꼭 위와 같이 해결하지 않아도 되지만, 예시로 사용된 코드에는 적용할만한 해결법인 것 같습니다.
동적할당의 장단점은 명확합니다. 그만큼 설계자에게 큰 책임이 따릅니다.
하지만, 철저하게 관리하여 사용한다면 동적할당은 매우 훌륭한 도구가 되어 줄 수 있습니다.
'C++' 카테고리의 다른 글
스마트 포인터 - weak_ptr, unique_ptr (0) | 2024.05.27 |
---|---|
스마트 포인터 - shared_ptr (0) | 2024.05.27 |
iterator(반복자) (0) | 2024.04.29 |
오른값 참조 (0) | 2024.04.22 |
얕은 복사 VS 깊은 복사 (0) | 2024.04.21 |