r5sdk/r5dev/tier0/memstd.cpp
Kawe Mazidjatari ef69611435 Replace memalloc calls throughout entire SDK
Global 'direct' usage of 'MemAllocSingleton()' has been jettisoned. Where possible, smart pointers were used instead. During the refactor, the following bugs were addressed and fixed:
- The virtual destructor of 'CCVarIteratorInternal' was NOT called on destruction.
- Class function 'KeyValues::MakeCopy' did NOT calculate the buffer size of the wide string correctly, the original calculation was 'len+1*sizeof(wchar_t)', but should've been '(len+1)*sizeof(wchar_t)'.

Some other code changes include:
- Tier0 include 'memstd.h' has been moved above all thirdparty includes, to make sure the memalloc functions get shadowed with ours in third party libraries as well.
- RPak file paths string literals are now defines.
- 'DestroyOverlay' has been refactored to match the assembly of the game.
2023-06-26 22:34:24 +02:00

107 lines
2.7 KiB
C++

//=============================================================================//
//
// Purpose:
//
//=============================================================================//
#include "memstd.h"
static bool s_bAllocatorInitialized = false;
static void InitAllocator()
{
if (!s_bAllocatorInitialized)
{
s_bAllocatorInitialized = true;
// https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
const PEB64* processEnvBlock = reinterpret_cast<PEB64*>(__readgsqword(0x60));
const QWORD imageBase = processEnvBlock->ImageBaseAddress;
CreateGlobalMemAlloc = CModule::GetExportedSymbol(imageBase,
"CreateGlobalMemAlloc").RCast<CStdMemAlloc* (*)(void)>();
g_pMemAllocSingleton = CModule::GetExportedSymbol(imageBase,
"g_pMemAllocSingleton").DerefSelf().RCast<CStdMemAlloc*>();
}
}
//=============================================================================//
// Reimplementation of standard C functions for memalloc callbacks
// ---------------------------------------------------------------------------
// The replacement functions use the game's internal memalloc system instead
//=============================================================================//
extern "C" void* R_malloc(size_t nSize)
{
Assert(nSize);
InitAllocator();
return MemAllocSingleton()->Alloc(nSize);
}
extern "C" void R_free(void* pBlock)
{
//Assert(pBlock);
InitAllocator();
MemAllocSingleton()->Free(pBlock);
}
extern "C" void* R_realloc(void* pBlock, size_t nSize)
{
//Assert(pBlock && nSize);
InitAllocator();
if (nSize)
return MemAllocSingleton()->Realloc(pBlock, nSize);
else
{
MemAllocSingleton()->InternalFree(pBlock, "tier0_static128", 0);
return nullptr;
}
}
extern "C" char* R_strdup(const char* pString)
{
Assert(pString);
InitAllocator();
const size_t nLen = strlen(pString) + 1;
void* pNew = MemAllocSingleton()->Alloc(nLen);
if (!pNew)
return nullptr;
return reinterpret_cast<char*>(memcpy(pNew, pString, nLen));
}
extern "C" void* R_calloc(size_t nCount, size_t nSize)
{
Assert(nCount && nSize);
InitAllocator();
const size_t nTotal = nCount * nSize;
void* pNew = MemAllocSingleton()->Alloc(nTotal);
memset(pNew, NULL, nTotal);
return pNew;
}
extern "C" size_t R_mallocsize(void* pBlock)
{
InitAllocator();
size_t nSize = MemAllocSingleton()->GetSize(pBlock);
return nSize;
}
// !TODO: other 'new' operators introduced in C++17.
void* operator new(std::size_t n) noexcept(false)
{
return malloc(n);
}
void operator delete(void* p) throw()
{
return free(p);
}