Stomp Allocator
카테고리: Server
인프런에 있는 루키스님의 게임 서버 강의를 듣고 정리한 내용입니다.
메모리 오염
Knight* knight = new Knight(100);
delete(knight);
knight->_hp = 100;
- 가장 자주 발생하는 메모리 오염은 Use After Free(댕글링 포인터) 문제
- delete를 하게 되면 쓰레기 값이 들어가긴 하는데, 웃긴게 접근은 가능함
- 나중에 문제 발생
Player* p = new Player();
Knight* k = static_cast<Knight*>(p);
k->_hp = 200;
- 또 다른 하나는 상속 관계 클래스를 다루다가 발생하는 캐스팅 실수
dynamic_cast
를 사용하면 방지할 수 있는데 느려서 안쓰는 경우가 많음- 범위를 넘어서는 메모리를 건드는 것이기 때문에 사실상 overflow 문제
Stomp Allocator
void* StompAllocator::Alloc(int32 size)
{
const int64 pageCount = (size + PAGE_SIZE - 1) / PAGE_SIZE;
const int64 dataOffset = pageCount * PAGE_SIZE - size;
void* baseAddress = ::VirtualAlloc(NULL, pageCount * PAGE_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
return static_cast<void*>(static_cast<int8*>(baseAddress) + dataOffset);
}
void StompAllocator::Release(void* ptr)
{
const int64 address = reinterpret_cast<int64>(ptr);
const int64 baseAddress = address - (address % PAGE_SIZE);
::VirtualFree(reinterpret_cast<void*>(baseAddress), 0, MEM_RELEASE);
}
VirtualAlloc
,VirtualFree
: 페이지 단위로 메모리 할당, 권한 부여- 댕글링 포인터 접근하면 크래쉬!
- dataOffset을 이용해 메모리를 사용하는 메모리를 오른쪽으로 밀어주면, overflow 문제도 탐지할 수 있음
/*----------------
Memory
-----------------*/
#ifdef _DEBUG
#define Xalloc(size) StompAllocator::Alloc(size)
#define xrelease(ptr) StompAllocator::Release(ptr)
#else
#define Xalloc(size) BaseAllocator::Alloc(size)
#define xrelease(ptr) BaseAllocator::Release(ptr)
#endif
Stomp Allocator는 메모리 오염 문제를 사전에 방지할 수 있기 때문에 매우 편리하지만 메모리 할당의 기본 단위가 페이지(4096 byte)이기 때문에 실질적으로 사용하기 어렵다. 따라서 Macro를 이용해 디버그 모드에서만 Stomp Allocator를 사용해 메모리 오염을 방지하고, 실제 릴리즈 모드에서는 일반적인 메모리 할당을 사용하면 된다.
댓글 남기기