0. 필요성
실제 게임에서는 동시 접속자 수가 1명이든 5만명이든 몬스터는 항상 1마리에서 500만 마리 이상이다.
이 수많은 몬스터를 스택 영역(스택 오버플로우)이나 메모리 영역에서 구현할 수는 없다.
따라서 필요할 때만 사용할 수 있으며 객체의 생성 시점과 소멸 시점을 관리할 수 있는 영역이 필요하다.
=> HEAP 영역
0.5 운영체제의 메모리 관리
유저 영역과 커널 영역으로 나뉘어져 있다. 커널 영역에서는 운영체제 전반의 구동, 유저 영역에서는 프로그램의 구동이 이뤄진다.
유저 영역의 각 프로그램들은 각기 격리된 메모리 영역을 차지하고, 가용 메모리가 적어지면 다음의 단계로 메모리를 확보한다.
유저 영역에서 API 호출 -> 커널 영역에서 여유 메모리를 할당 후 전달
1. Heap 관련 함수
C++ 에서는 C 런타임 라이브러리에 포함된 힙 관리자를 이용하여 힙 영역을 사용한다.
필요에 따라서 API에 직접 접근하여 힙을 생성하거나 관리할 수 있다.
(1) 메모리 할당 : malloc(size)
할당할 메모리의 크기를 건네주고 할당 이후에 시작 주소를 가리키는 포인터를 반환한다.
void* pointer = malloc(1000); // 1000바이트를 할당하고 시작 주소를 반환
void*는 타입을 자동으로 판단하게 한다.
다만 sizeof를 이용하여 메모리 낭비를 줄이는 방법도 있다.
void* pointer = malloc(sizeof(Monster)); // 몬스터의 크기 만큼의 메모리를 할당하고 시작주소를 반환
int main()
{
Monster* m1 = (Monster*) pointer;
m1->_hp = 100;
m1->_x = 10;
m1->_y = 5;
return 0;
}
- 힙 오버플로우(Heap Overflow)
할당된 메모리 영역을 초과하여 사용하는 경우 발생.
(2) 메모리 할당 해제 : free(pointer)
포인터에는 몬스터 크기 만큼의 메모리 영역이 할당되어 있으며 그 시작 주소가 저장되어 있는데
free 함수를 사용하여 해당 주소를 찾아가서 메모리 영역을 해제시킬 수 있다.
int main()
{
Monster* m1 = (Monster*) pointer; // Monster 클래스의 객체 m1을 만들고 포인터를 대입
//~~~
free(pointer);
return 0
}
- 메모리 누수
free를 이용하지 않는 경우 메모리가 반환되지 않아서 크래시가 발생.
- 더블 프리(Double Free)
free를 연속 호출하여 크래시가 발생.
- Use-After-Free
반납된 메모리의 주소가 그대로 포인터에 저장되어 있는 상황에서 해당 포인터를 수정하는 상황.
-> 수정하려는 값과 상관없는 다른 값이 수정될 수 있는 심각한 문제가 발생.
=> 이를 방지하기 위해 포인터를 null로 만들어주는 것이 필요함.
free(pointer);
m1 = nullptr;
pointer = nullptr;
2. Heap 관련 연산자
(1) new 연산자
new 연산자는 메모리를 할당하고 객체를 생성하여 시작 주소를 반환한다. 또한 형 변환을 자동으로 해준다.
//~~
Monster* m2 = new Monster;
m2->_hp = 200;
m2->_x = 2;
m2->_y = 2;
delete m2;
//~~
new 연산자를 이용하여 만든 객체 m2와 위에서 malloc을 사용하여 만든 객체 m1의 코드를 비교해보면
형 변환을 직접적으로 넣어줬던 m1과는 달리 m2는 자동으로 형 변환을 했다는 것을 알 수 있다.
(2) delete 연산자
new 연산자로 만든 객체의 메모리 할당을 해제한다.
발생할 수 있는 오류는 free와 동일하다.
(3) 배열 형태로 객체 생성
// ~~
Monster* m3 = new Monster[5];
m3->_hp = 200;
m3->_x = 2;
m3->_y = 3;
delete[] m3;
// ~~
Monster 하나에 할당된 메모리에 N을 곱한 숫자 만큼의 메모리를 할당한다.
Monster* m4 = (m3 + 1);
m4->_hp = 200;
m4->_x = 2;
m4->_y = 3;
delete[] m4;
delete[ ] 문법에 주의하도록 한다.
3. 특징
(1) heap 함수 (malloc / free)
- 타입에 상관없이 특정 크기의 메모리 영역을 할당 할 수 있다.
(2) heap 연산자 (new / delete)
- 사용 편의성이 높다(행 변환을 자동으로 해준다).
- 생성 타입이 클래스이면 생성자와 소멸자를 호출한다 => OOP 친화적
'기초 C++ 스터디 > 객체지향' 카테고리의 다른 글
6-3. 형(Type) 변환 : 포인터 (2) (0) | 2023.06.01 |
---|---|
6-2. 형(type) 변환 (1) (0) | 2023.05.31 |
5-7. 객체지향 정리 (0) | 2023.05.30 |
5-6. 연산자 오버로딩 (0) | 2023.05.30 |
5-5. 초기화 리스트 (0) | 2023.05.26 |