⚠️ 왜 Allocator가 필요할까?

1. 컨텍스트 스위칭 비용

new를 호출하면 운영체제 커널에 메모리를 요청하게 되는데, 이때 컨텍스트 스위칭(context switching) 이 발생할 수 있다. 메모리를 자주 할당/해제하는 상황에서는 이 컨텍스트 스위칭이 성능 병목이 될 수 있다.

🔧 해결 방법: 한 번에 큰 메모리를 받아 놓고 사용자 레벨에서 쪼개서 관리하면 된다. → 메모리 풀(Pool) 기법

2. 메모리 단편화(Fragmentation)

작은 크기의 메모리를 반복해서 할당/해제하다 보면 빈틈이 있는 메모리 공간이 많아지고, 사용할 수 있는 공간은 있지만 연속적이지 않아 할당 실패가 발생하는 문제가 생긴다.

🔧 해결 방법: 메모리를 효율적으로 관리할 수 있는 커스텀 할당자 작성


✏️ 커스텀 Allocator 구현

🔹 BaseAllocator

// Allocator.h
#pragma once

class BaseAllocator {
public:
	static void* Alloc(int32 size);
	static void  Release(void* ptr);
};
// Allocator.cpp
void* BaseAllocator::Alloc(int32 size) {
	return ::malloc(size);
}
void BaseAllocator::Release(void* ptr) {
	::free(ptr);
}
  • malloc, free를 감싼 간단한 구조
  • 추후에 다른 메모리 풀 정책으로 대체하기 쉬운 구조

🔹 CoreMacro 매크로 정의

// CoreMacro.h

#ifdef _DEBUG
#define xalloc(size)		BaseAllocator::Alloc(size)
#define xrelease(ptr)		BaseAllocator::Release(ptr)
#else
#define xalloc(size)		BaseAllocator::Alloc(size)
#define xrelease(ptr)		BaseAllocator::Release(ptr)
#endif
  • xalloc, xrelease를 통해 메모리 할당을 더 간결하게 표현

🔹 xnew / xdelete 구현

// Memory.h
#pragma once
#include "Allocator.h"

template<typename Type, typename... Args>
Type* xnew(Args&&... args)
{
	Type* memory = static_cast<Type*>(xalloc(sizeof(Type)));
	new(memory) Type(std::forward<Args>(args)...); // placement new
	return memory;
}

template<typename Type>
void xdelete(Type* obj)
{
	obj->~Type();      // 소멸자 직접 호출
	xrelease(obj);     // 메모리 해제
}
  • xnew: 메모리만 할당 후 생성자 호출
  • xdelete: 소멸자 호출 후 메모리 반환
  • placement new: 이미 할당된 메모리 위에 객체를 생성

👨‍🔬 테스트 예제

class Unit {
public:
	Unit(int hp) : _hp(hp) {
		cout << "Unit(hp)" << endl;
	}
	~Unit() {
		cout << "~Unit()" << endl;
	}
	int _hp = 100;
};

int main() {
	Unit* unit = xnew<Unit>(200);
	xdelete(unit);
}

출력:

Unit(hp)
~Unit()
  • 생성자/소멸자 모두 정상 호출됨
  • xnewxdeletenew, delete와 동일한 기능을 수행하는 것을 확인

🧩 Placement New란?

new(memory) Type(args...);
  • 이미 할당된 메모리에 객체를 생성
  • 메모리를 미리 확보하고 생성자를 호출하는 방식
  • 일반 newmalloc + 생성자 호출이라면, placement new는 사용자 지정 메모리 + 생성자 호출

📝 사용 이유

문제해결 방식
빈번한 컨텍스트 스위칭한 번에 큰 메모리 요청, 유저레벨에서 분할
메모리 단편화메모리 풀로 연속적인 공간 관리
new/delete가 느림직접 메모리 관리 구조 작성
생성자 호출 제어placement new 사용

profile
李家네_공부방

0개의 댓글