vector<int> v{ 0, 1, 2, 3, 4 };
for (int i = 0; i < 5; i++) {
int value = v[i];
if (value == 1)
v.clear();
}
v.clear() 이후에도 v[i]로 접근하게 되면 런타임 에러 발생Unit* unit = new Unit();
delete unit;
unit->_hp = 100; // ?? 오류 안 나지만 위험한 접근
PUnit* p = new PUnit();
Unit* u = static_cast<Unit*>(p); // 실제로는 Unit이 아님
u->_hp = 10; // 오류 발생 가능
class StompAllocator
{
enum { PAGE_SIZE = 0x1000 }; // 4KB
public:
static void* Alloc(int32 size);
static void Release(void* ptr);
};
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);
}
#ifdef _DEBUG
#define xxalloc(size) StompAllocator::Alloc(size)
#define xxrelease(ptr) StompAllocator::Release(ptr)
#else
#define xxalloc(size) BaseAllocator::Alloc(size)
#define xxrelease(ptr) BaseAllocator::Release(ptr)
#endif
이 매크로를 사용하면 xnew, xdelete에 자동 적용되므로 기존 코드 수정 없이 디버그 환경에서만 StompAllocator를 사용할 수 있다.
class Knight
{
public:
int _hp = 100;
};
int main()
{
Knight* knight = static_cast<Knight*>(xxalloc(sizeof(Knight)));
knight->_hp = 200;
xxrelease(knight);
knight->_hp = 300; // 💥 Use-After-Free 오류 즉시 발생!
}
[ [ 객체 데이터 ] ]
↑ 메모리 끝에 위치
VirtualAlloc: 메모리 예약 및 실제 할당VirtualFree: 메모리 완전 해제SYSTEM_INFO info;
::GetSystemInfo(&info);
cout << "Page Size: " << info.dwPageSize << endl; // 4096
cout << "Granularity: " << info.dwAllocationGranularity << endl; // 65536