이 글은 [인프런-게임서버 만들기 by rookiss]를 내용을 토대로 개인적으로 학습한 내용을 종합하여 정리 했습니다.
목표
운영체제에 직접 메모리를 할당/해제 요청 함으로써 잘못된 메모리 접근을 막는다.
구현
void* StompAllocator::Alloc(int32 size)
{
// 페이지 사이즈 단위로 반올림.
const int64 pageCount = (size + PAGE_SIZE - 1) / PAGE_SIZE;
const int64 reqSize = pageCount * size;
return ::VirtualAlloc(NULL, pageCount * PAGE_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);;
}
void StompAllocator::Release(void* ptr)
{
::VirtualFree(ptr, 0, MEM_RELEASE);
}
애초에 작은 공간을 요청해도 페이지 단위로 할당하기 때문에 페이지 사이즈 단위로 요청하는 코드이다.
적용
template<typename Type, typename... Args>
Type* xnew(Args&&... args)
{
Type* memory = static_cast<Type*>( StompAllocator::Alloc(sizeof(Type)) );
new(memory)Type(::forward<Args>(args)...);
return memory;
}
template<typename Type>
void xdelete(Type* obj)
{
obj->~Type();
StompAllocator::Alloc(obj);
}
이전 단계에서 만든 xnew / xdelete의 메모리 할당 해제 부분을 stomp allocator로 대체 했다.
개선점
지금까지의 stomp allocator로 할당된 메모리에 접근하는 잘못된 메모리를 접근을 방지할 수 있지만 메모리가 해제 되지 않은 상태에서 잘못된 메모리 참조는 여전히 가능하다. 메모리 할당이 페이지 단위로 이루어 지기 때문에 4byte 객체를 생성해도 64byte가 할당되고 사용하지 않는 메모리 참조가 가능하게 되는 오버플로우 문제가 발생한다. 이를 해결하기 위한 방법을 알아보자.
해결 idea
사용할 메모리를 우측 정렬 한다.
기존 메모리 구조 => [o][o][o][x][x][x][x][x][x][x]
메모리를 우측 정렬 => [x][x][x][x][x][x][x][o][o][o]
구현
void* StompAllocator::Alloc(int32 size)
{
// 페이지 사이즈 단위로 반올림.
const int64 pageCount = (size + PAGE_SIZE - 1) / PAGE_SIZE;
const int64 dataOffset = pageCount * PAGE_SIZE - size;
const int64 reqSize = pageCount * size;
void* base = ::VirtualAlloc(NULL, pageCount * PAGE_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);;
return static_cast<void*> ( static_cast<char*>(base) + dataOffset );
}
void StompAllocator::Release(void* ptr)
{
// 메모리는 프로세스에 메모리가 64kb로 할당 되고
// 메모리 요청은 페이지 단위 4kb 할당 되기 떄문에
// 4kb로 나머지 연산한 값이 offset 값임을 알 수 있다.
const int64 address = reinterpret_cast<int64>(ptr);
const int64 baseAddress = address - (address % PAGE_SIZE);
::VirtualFree(reinterpret_cast<void*>(baseAddress), 0, MEM_RELEASE);
}
offset을 구해서 char* 타입 포인터 값과 포인터 연산을 한 모습이다. 이렇게 되면 반대로 언더플로우 문제가 생길 수 도 있으나 오버플로우 처럼 일반적인 경우는 아니기 때문에 신경 쓰지 않기로 한다.
결론
해제된 메모리의 잘못된 접근을 막는다.
할당 메모리의 오버플로우 문제를 막는다.(언더플로우는 못 막음)
'Programming Language > C++' 카테고리의 다른 글
[인강/코드없는 프로그래밍] 병렬 프로그래밍을 필요한 이유 (0) | 2022.02.21 |
---|---|
[인강/코드없는 프로그래밍] false sharing (0) | 2022.02.20 |
CustomAllocator] 6단계_stl allocator (0) | 2022.02.14 |
CustomAllocator] 4단계_StompAllocator_1 (0) | 2022.02.14 |
CustomAllocator] 3단계_메모리 페이징 (0) | 2022.02.14 |