이 프로젝트에서 동적으로 할당된 메모리를 해제할 때는 SAFE_DELETE라는 매크로 함수를 사용한다.
#define SAFE_DELETE(p) if(p){delete p;p=NULL;}
포인터 p에 할당되어있는 메모리를 해제하고 p를 NULL로 지정한다. SAFE_DELETE를 사용하면 아무 이상 없어보이지만 문제는 동적 할당한 포인터를 여러 객체에서 참조하고 있을 때 나타난다.
class Ref {
public:
int value = 1;
};
class A {
public:
Ref* r1;
};
class B {
public:
Ref* r2;
};
int main()
{
Ref* r = new Ref;
A a;
B b;
a.r1 = r;
b.r2 = r;
cout << a.r1->value << '\n' << b.r2->value <<'\n';
delete r;
cout << a.r1->value << '\n' << b.r2->value;

Ref 포인터를 참조하고 있는 클래스 A와 B는 동적으로 할당된 Ref가 해제되고 둘 다 쓰레기 값을 가진다. 그래서 프레임 워크에서 한 클래스에서 사용이 끝났다고 delete를 해버리면 다른 참조하고 있는 클래스에서 사용할 수 없어진다.
void AddRef()
{
++m_iRef;
}
int Release()
{
--m_iRef;
if (m_iRef == 0)
{
delete this;
return 0;
}
return m_iRef;
}
그래서 사용하는 것이 Reference Count이다. Ref 라는 클래스를 만들어 m_iRef 변수로 참조되는 횟수를 저장한다.
Ref는 Object가 상속받아 이 Object가 몇번이나 참조되었는지 알 수 있다. 그래서 참조될 때 마다 AddRef를 하고
사용이 끝난 후 Release를 한다. 그래서 참조횟수가 0이되면 delete로 메모리를 해제한다.
#define SAFE_RELEASE(p) if(p) {p->Release();p=NULL;}
매크로 함수 코드는 위와 같으며 Ref.h의 Release 함수를 사용해야 하므로 p는 Ref 클래스를 상속받아야 한다.
CPlayer* pPlayer = CObj::CreateObj<CPlayer>("Player", pLayer);
SAFE_RELEASE(pPlayer);
위 코드는 InGameScene::Init 에서 플레이어를 생성하는 예시이다. CObj::CreateObj 템플릿으로 CPlayer 타입의 오브젝트를 생성하여 Layer가 가지고 있는 Object List에 추가하고, Object가 가지고 있는 static list에 한번 더 추가했다. 그래서 AddRef를 2번해서 pPlayer의 m_iRef는 3이 된다. m_iRef는 최초 생성시에 1이다. (생성한 것이 최초로 참조한 것과 같기 떄문에) 그리고 pPlayer을 Layer와 Object에 추가하는 것을 마쳤기 때문에 InGameScene에서는 사용할 일이 없으므로 SAFE_RELEASE 해준다. 그러면 pPlayer의 m_iRef는 2가 되고 NULL이 된다. Layer와 Object에 추가된 pPlayer은 NULL이 되지 않고 감소된 m_iRef만 적용된다.
'WinAPI' 카테고리의 다른 글
| [WinAPI] 게임 프레임워크 - 5. PathManager, 유니코드와 멀티바이트 (0) | 2022.02.02 |
|---|---|
| [WinAPI] 게임 프레임워크 - 4. Input (0) | 2022.02.02 |
| [WinAPI] 게임 프레임 워크 - 2. Scene과 SceneManager (0) | 2022.02.01 |
| [Winapi] 게임 프레임워크 - 1. Core (0) | 2022.02.01 |
| [WinAPI] Pivot (0) | 2022.01.20 |