(C++ : IOCP-16) Allocator

Posted by : at

Category : Cpp   iocp



메모리를 단순 new, delete로 관리하지말고 미리 Allocate해둔 후 관리해 보자.

왜 그렇게 해야할까?

  • 우선 Windows기반에서는 메모리관리를 OS에서 해준다.
  • 할당해야할 메모리가 많아진다면 OS의 커널영역에서 새로운 메모리 할당을 하며 컨텍스트 스위칭비용이 발생하는데 그 비용을 감소시키기 위함이 있고
  • 또한 메모리 파편화 현상을 방지하는데 내가 메모리를 Allocate해서 관리하면 좋기 때문이다.

  • 우선 이번강에서는 위 문제를 해결한순 없다. 단, new, delete를 이렇게 개발자가 커스터마이징 가능하다는 것을 이해하자

그럼 구현을 해보자.


우선 newdelete를 개발자가 새로 구현해야한다.

// new, delete를 어떻게 커스터마이징 할까

// new operator overloading (Global)
void* operator new(size_t size)
{
	cout << "new! " << size << endl;
	void* ptr = ::malloc(size);
	return ptr;
}

void operator delete(void* ptr)
{
	cout << "delete!" << endl;
	::free(ptr);
}

void* operator new[](size_t size)
{
	cout << "new[]! " << size << endl;
	void* ptr = ::malloc(size);
	return ptr;
}

void operator delete[](void* ptr)
{
	cout << "delete![]" << endl;
	::free(ptr);
}

// 생각보다 간단...
// 단, 이렇게 전역으로 구현하면 의도치 않은 new와 delete에도 영향을 줄 수 있다.
class Knight
{
public:
	Knight()
	{
		cout << "Knight()" << endl;
	}

	Knight(int32 hp) : _hp(hp)
	{
		cout << "Knight(hp)" << endl;
	}

	~Knight()
	{
		cout << "~Knight()" << endl;
	}

    // 이렇게 객체안에 넣어서도 구현가능
	static void* operator new(size_t size)
	{
		cout << "Knight new! " << size << endl;
		void* ptr = ::malloc(size);
		return ptr;
	}

	static void operator delete(void* ptr)
	{
		cout << "Knight delete!" << endl;
		::free(ptr);
	}

	int32 _hp = 100;
	int32 _mp = 10;
};

그럼 매번 클래스 안에 new, delete를 구현해야 할까?
해결해보자

// 새로운 new, delete를 만들어 보자

#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
void* BaseAllocator::Alloc(int32 size)
{
	return ::malloc(size);
}

void BaseAllocator::Release(void* ptr)
{
	::free(ptr);
}
#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(forward<Args>(args)...); // placement new - 여기가 헷갈린다(지연 생성)
    // new(memory) : 메모리는 이미할당되어 있으니 할당하지말고
    // Type(forward<Args>(args)...) : 요렇게 생성자만 호출해 줘
	return memory;
}

template<typename Type>
void xdelete(Type* obj)
{
	obj->~Type();
	xrelease(obj);
}

실사용은 이렇게

int main()
{	
	Knight* knight = xnew<Knight>(100);

	xdelete(knight);
}

About Taehyung Kim

안녕하세요? 8년차 현업 C++ 개발자 김태형이라고 합니다. 😁 C/C++을 사랑하며 다양한 사람과의 협업을 즐깁니다. ☕ 꾸준한 자기개발을 미덕이라 생각하며 노력중이며, 제가 얻은 지식을 홈페이지에 정리 중입니다. 좀 더 상세한 제 이력서 혹은 Private 프로젝트 접근 권한을 원하신다면 메일주세요. 😎

Star
Useful Links