설탕중독 2022. 6. 21. 00:29

 

동적 할당

 

동적 할당은 왜 필요한 것일까?

우선 다른 저장 영역의 특징을 간략하게 살펴보자

 

- 스택 영역

함수가 끝나면 같이 사라지는 불안정한 저장 공간

잠시 함수에 매개변수를 넘기는 등의 용도로 사용

 

- 메모리 영역

프로그램이 실행되는 동안은 무조건 사용되는 저장 공간

어떠한 상황이든 프로그램이 실행되는 동안 할당된 크기만큼의 저장 공간이 사용됨

 

스택과 메모리 영역으로도 많은 것을 만들 수 있지만 이 두 가지를 이용해서 만들기엔

불가능하거나 비효율적인 상황이 있다. 예를 들어 사용자가 필요한 만큼만 메모리를 사용하고

이후에 필요가 없어지면 언제든 반환할 수 있는 이런 시스템이 필요한 상황이 존재한다.

그래서 사용되는 것이 동적 할당(HEAP-힙 영역)이다. 

 

동적 할당은 스택과는 다르게 생성과 소멸 시점을 관리할 수 있다는 장점이 있다.

위에서 말했듯이 필요한 만큼만 사용하고, 다 사용했으면 반환할 수 있다.

 

C++에서는 기본적으로 CRT(C런타임 라이브러리)의 '힙 관리자'를 통해 힙 영역을 사용한다.

단, 정말 원한다면 사용자가 직접 API를 통해 힙을 생성하고 관리할 수도 있다.

(이런 상황은 보통 MMORPG 서버에서 메모리 풀링 같은 고급 기법을 이용해서 사용할 수 있다.)


동적 할당과 연관된 함수/연산자 종류 : malloc, free, new, delete, new[], delete[]

 

이 중에서 malloc과 free는 함수이다.

new와 delete는 연산자이다.

 

void* a = malloc(1000);

위와 같이 호출하였을 때 1000바이트만큼 메모리 할당 후 할당된 메모리의 시작 주소를 가리키는

포인터를 반환해준다. (메모리가 부족하면 NULL 포인터 반환)

 

free(a);

malloc과 짝꿍인 존재로 할당된 메모리 영역을 해제하는 역할을 한다.

 

동적 할당을 잘못 사용하면 큰 문제가 될 수 있다. 

메모리를 할당하고 free를 하지 않아서 메모리 누수가 발생한다던가

free를 해서 할당을 해제했지만 포인터 주소를 nullptr로 밀어주지 않아서 주소는 살아 있고 

나중에 해당 포인터 주소를 멋대로 사용해서 메모리 영역이 오염되는 상황이 발생할 수도 있다.

그렇기 때문에 꼼꼼하게 체크해가며 사용할 필요가 있다.

 

int* x = new int;

new의 사용법이다. 연산자이기 때문에 malloc과는 사용 방법에 차이가 있다. 하지만 실제 기능은

동일하다 malloc과 마찬가지로 동적 할당을 하며 필요한 만큼 사용한 후 delete를 이용해서 반환

하면 된다. 

 

delete x;

new와 한 세트이다. 동적 할당받은 메모리를 다 사용한 후 반환할 때 사용한다.

 

위와 같은 new 방식은 한 개의 int 값만을 만들기 때문에 여러모로 아쉬운 부분이 있다.

그래서 등장한 것이 배열을 이용한 방식이다. 

 

int* y = new int[5];

int형 5개를 만들어준다. 일반 new와 동일한 기능을 하며 첫 시작 주소를 반환한다.

 

int* yy = (y + 1);

변수 y는 동적 할당받은 메모리의 시작 주소를 가리키고 있기 때문에 다음 주소부분을 활용하기

위해서는 y 주소에서 +1을 해줘서 다음 주소를 yy 변수에 넣어 사용할 수 있다.

 

delete[] y;

배열 방식을 이용해서 동적 할당받은 메모리를 반환할 때 사용한다. 꼭 짝꿍을 맞춰야 한다.

new/delete, new[]/delete[] 짝꿍을 맞춰서 사용해야 에러가 발생하지 않는다.

 

 

malloc/free와 new/delete 비교

- 사용성이나 편의성은 new/delete가 좋다.

- 타입에 상관없이 특정한 크기의 메모리 영역을 할당받으려면 malloc/free가 좋다.

 

둘의 가장 중요하고 근본적인 차이는?

new/delete는 생성 타입이 클래스일 경우 생성자/소멸자를 호출해 준다.

(malloc/free는 생성자/소멸자를 호출하지 않는다.)

 

C++은 메모리 영역을 자유자재로 사용할 수 있다는 것이 장점이자 단점이다.

항상 메모리를 다루는 것은 긴장해야 하고 조심해야 한다는 것을 기억하자.