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