동적 할당
-> 메모리 영역 중 Heap 영역에 저장된다.
-> 사용자가 원할때 메모리에 등록시키고, 사용자가 원할때 메모리에서 해제할 수 있다.
-> 단, 동적 할당한 메모리를 해제하지 않을 경우 메모리 누수가 발생한다.
-> 프로그램을 종료해도 메모리에 계속해서 상주한다.
-> 동적 할당은 C방식과 C++방식으로 나눠진다.
C 기반 동적 할당
char* pName = nullptr;
pName = Func();
cout << pName << endl;
pName은 Func함수가 반환하는 값을 저장한다.
-> Func함수에는 szBuff라는 지역 변수가 있다.
-> Func함수가 반환하는 값은 해당 지역 변수의 할당 주소이다.
-> Func함수가 종료되면 stack 영역을 정리하면서 지역 변수의 할당 메모리 영역을 소멸시킨다.
-> 결과적으로 pName은 소멸될 공간의 주소를 받아오는 상황이다.
동적 할당 방법
#1 malloc()
-> void* : 시작 주소를 반환한다.
-> 단, 해당 시작 주소는 몇 바이트만큼 어떤 형식으로 읽을지 모르는 상황이다.
-> 이를 정상적으로 사용하기 위해서는 형 변환을 진행해야 한다.
malloc 함수를 선언하고 마우스를 올려보면 (size_t Size)가 보인다.
size_t _Size는 Heap 영역에 얼마만큼 메모리 공간을 할당할지 byte단위로 크기를 전달한다.
malloc(4)라고 선언하면 Heap 영역에 4byte만큼 공간을 할당한다는 의미이다.
malloc 함수 형 변환
(int*)malloc(4);
-> 할당한 공간의 주소를 반환할 때 int*형으로 형 변환해서 반환
int* ptr = (int*)malloc(4);
cout << "ptr: " << ptr << endl; // Heap 영역의 주소
cout << "*ptr: " << *ptr << endl; // heap 영역의 주소에 할당한 값
Heap영역에 4bytes만큼 할당 후 해당 공간의 시작 주소를 반환하는데,
int*형으로 변환하여 ptr이라는 변수에 저장한다.
동적할당 해제
-> 동적할당을 해제 할 때는 free() 함수를 사용하면 된다.
그런데 동적할당을 해제 했음에도 주소 값이 그대로 있다.
-> 이유는 동적 할당된 메모리를 해제는 완료하였지만 주소 값은 그대로 남아있는 상황이 발생해서 그렇다.
-> 이것을 Dangling Pointer라고 한다.
Dangling Pointer(위험한 주소)
-> 동적할당을 해제한다해도 변수의 주소는 그대로 남아 있다.
Dangling Pointer가 발생하는 경우.
-> #1 할당되지 않은 메모리 공간의 접근
-> #2 다른 변수에서 동적할당한 곳이 같은 곳을 할당 받을 경우
Dangling Pointer 예방 방법
-> free 함수를 호출 후 변수를 nullptr로 초기화하는 습관을 들여야한다.
calloc()
-> size_t _Count : 몇 개를 할당할 것인지 전달.
-> 동적 배열을 만들 때 사용한다.
4bytes 공간을 3개 할당(동적 배열)
calloc(3, 4);
calloc으로 동적 배열 만들기
int iSize = 0;
cin >> iSize;
int* pArr = (int*)calloc(iSize, sizeof(int));
for (int i = 0; i < iSize; ++i)
cout << pArr[i] << endl;
malloc으로 동적 배열 만들기
int iSize = 0;
cin >> iSize;
int* pArr = (int*)malloc(sizeof(int) * iSize);
for (int i = 0; i < iSize; ++i)
cout << pArr[i] << endl;
malloc과 calloc의 차이점
-> malloc은 쓰레기 값으로 초기화
-> calloc은 0으로 초기화가 진행된다.
지금까지 한 것은 C기반의 동적 할당이고,
이번에는 C++기반의 동적할당을 해보자.
C++ 기반의 동적 할당
new 연산자
사용 예)
new 자료형
int* ptr = new int;
Heap 영역에 자료형의 크기만큼 공간을 할당하고,
자료형의 포인터형으로 주소를 형 변환하여 반환한다.
동적 할당 해제
delete
delete ptr;
ptr = nullptr
C기반은 포인터를 초기화 하지 않고 동적 할당을 해제하면 주소 값이 그대로 남지만,
C++ 기반은 다른 곳에서 동적 할당할 경우에 같은 주소를 참조하지 않게 다른 곳으로 주소가 바뀐다.
이 경우 역참조를 이용하여 데이터를 다룰 경우 오류가 발생한다.
C++ 기반 역시 Dangling Pointer 때문에 동적 할당을 해제하고나서 포인터를 nullptr로 초기화 해줘야 한다.
동적할당과 동시에 초기화
-> C++ 기반은 동적 할당과 동시에 초기화가 가능하다.
int* ptr = new int(10);
C기반의 초기화
int a = 10;
C++기반의 초기화
int a(10);
C++기반의 동적 배열
int iSize = 0;
cin >> iSize;
int* ptr = new int[iSize];
동적 배열 해제 방법
ptr 변수로만은 Heap 영역에 할당된 공간이 배열인지 아닌지 알 수 없는 상황이다.
-> 컴파일러는 단순하게 자료형을 토대로 판단한다.
// 주소만 남기고 삭제
delete
ptr = nullptr;
// 전체 삭제
delete[]
ptr = nullptr;
// 동적 배열 삭제
delete[] (ptr);
ptr = nullptr;
모든 메모리 할당은 직접 구현한 New, Delete 키워드를 통해 호출하는 것이 좋다.
'Programming > C++ Basic' 카테고리의 다른 글
C++ 경로 (0) | 2020.09.02 |
---|---|
C++ 입출력 스트림 버퍼, 단일 문자 입/출력 함수 (0) | 2020.09.02 |
C++ 구조체와 포인터 (0) | 2020.08.31 |
C++ 구조체(Struct) (0) | 2020.08.31 |
C++ 문자열 함수 (0) | 2020.08.31 |