자료실/C++

C++ - 동적 메모리 할당

자료수집중 2020. 8. 25.
반응형

 

 

C언어에서 동적 메모리 할당은 malloc()과 free()를 이용했습니다.

하지만 C++은 새롭게 new연산자와 delete연산자를 사용합니다.

동적 메모리 할당은 메모리의 비효율적인 사용을 관리하고자 사용합니다.

살짝 좀 더 알아보면 메모리는 몇 개의 영역으로 나눌 수 있습니다.

'동적 메모리 할당'은 메모리의 힙(heap)영역에 할당됩니다.

보통 우리가 컴파일 전에 할당하는 '정적 메모리 할당'은  대부분 스택(stack)영역을 사용합니다.

스택 영역도 당연하게도 크기를 초과하면 오버플로우가 발생합니다.

 

그래서 동적 메모리 할당에 대해서 알아보겠습니다.

먼저 동적 메모리 할당에는 new연산자를 사용합니다.

사용법도 malloc()에 비해서 굉장히 간단합니다.

int *num = new int;

포인터 변수에 new연산자를 이용해 해당 포인터 변수의 타입 크기를 메모리 할당만 하면 끝입니다.

 

메모리가 할당된 포인트 변수를 초기화하는 방법은

int *num = new int;
*num = 10;

또는

int *num = new int(10);

로 가능합니다.

 

 

동적 할당은 사용 후 더 이상 사용하지 않는다면 메모리를 꼭 해제해야 합니다.

해제하지 않으면 메모리 누수가 발생하므로 꼭 해제해야 합니다.
해제하는 방법은 delete연산자를 사용합니다.

int *num = new int;
*num = 10;
cout << *num << '\n';
delete num;

 

 

new연사자로도 동적 배열 할당이 가능합니다.

동적 배열을 할당할 때는 new[]를 사용합니다.

int *num = new int[10];
for (int i = 0; i < 10; i++) {
    num[i] = i;
}
for (int i = 0; i < 10; i++) {
    cout << num[i] << '\n';
}
delete[] num;

단 해제할 때도 delete가 아닌 delete[]를 사용해서 해제해야 합니다.

 

 

2차원 이상 배열도 할당이 가능합니다.

방법은 malloc()과 비슷합니다.

int **num = new int*[10];
for (int i = 0; i < 10; i++) {
    num[i] = new int[10];;
}

for (int i = 0; i < 10; i++) {
    delete[] num[i];
}
delete[] num;

2차원 배열을 예제로 봤을 때 이중 포인터에 1차로 배열을 할당한 다음 할당된 배열에 각각 다시 배열을 할당해 주는 방식입니다.

해제는 반대로 각각 배열에 할당된 2차 배열 메모리를 해제 후 마지막에 1차를 해제합니다.

 

 

추가적으로 댕글리 포인터(dangling pointer)에 대해 알아보겠습니다.

댕글리 포인터는 동적 할당이 되었다가 해제된 메모리를 뜻합니다.

해제가 되어도 포인터 변수가 해제된 메모리 주소를 가지고 있을 때 발생하는 문제입니다.

해제한 포인터 변수를 다시 사용한다던가 동적 할당된 포인터 변수를 다른 포인터 변수에 대입하는 상황에서 발생할 수 있습니다.

댕글리 포인터의 큰 문제점은 내가 정의하지 않은 동작이 발생 할 수 있다는 점입니다.

그래서 댕글리 포인터 예방하기 위해 해제한 포인터 변수에 nullptr를 대입합니다.

int *num = new int;
*num = 10;
cout << *num << '\n';
delete num;
num = nullptr;

포인터 변수가 nullptr인지 확인 후 사용이 가능합니다.

 

 

댓글