memory fun

Region.cpp/h: fix tile cache memory leaks by replacing raw malloc/free with RAII-compliant std::unique_ptr

Tesselator.cpp/h: fix thread-exit leaks by swapping unmanaged TlsAlloc for auto-cleaning C++17 thread_local std::unique_ptr (constructor now public)

LevelRenderer.cpp: fix heap corruption and array element leaks by changing 'delete' to 'delete[]' for chunk buffers
This commit is contained in:
Racc 2026-03-11 19:48:09 +00:00
parent 354c1d1738
commit 9aad2c8515
5 changed files with 26 additions and 38 deletions

View file

@ -367,19 +367,17 @@ void LevelRenderer::setLevel(int playerIndex, MultiPlayerLevel *level)
else
{
// printf("NULLing player %d, chunks @ 0x%x\n",playerIndex,chunks[playerIndex]);
if( chunks[playerIndex].data != nullptr )
{
for (unsigned int i = 0; i < chunks[playerIndex].length; i++)
{
chunks[playerIndex][i].chunk->_delete();
delete chunks[playerIndex][i].chunk;
}
delete chunks[playerIndex].data;
chunks[playerIndex].data = nullptr;
chunks[playerIndex].length = 0;
// delete sortedChunks[playerIndex]; // 4J - removed - not sorting our chunks anymore
// sortedChunks[playerIndex] = nullptr; // 4J - removed - not sorting our chunks anymore
}
if (chunks[playerIndex].data != nullptr)
{
for (unsigned int i = 0; i < chunks[playerIndex].length; i++)
{
chunks[playerIndex][i].chunk->_delete();
delete chunks[playerIndex][i].chunk;
}
delete[] chunks[playerIndex].data;
chunks[playerIndex].data = nullptr;
chunks[playerIndex].length = 0;
}
// 4J Stu - If we do this for splitscreen players leaving, then all the tile entities in the world dissappear
// We should only do this when actually exiting the game, so only when the primary player sets there level to nullptr
@ -451,7 +449,7 @@ void LevelRenderer::allChanged(int playerIndex)
chunks[playerIndex][i].chunk->_delete();
delete chunks[playerIndex][i].chunk;
}
delete chunks[playerIndex].data;
delete[] chunks[playerIndex].data;
// delete sortedChunks[playerIndex]; // 4J - removed - not sorting our chunks anymore
}

View file

@ -24,17 +24,16 @@ int normal;
*/
DWORD Tesselator::tlsIdx = TlsAlloc();
static thread_local std::unique_ptr<Tesselator> tlsInstance;
Tesselator *Tesselator::getInstance()
{
return static_cast<Tesselator *>(TlsGetValue(tlsIdx));
return tlsInstance.get();
}
void Tesselator::CreateNewThreadStorage(int bytes)
{
Tesselator *instance = new Tesselator(bytes/4);
TlsSetValue(tlsIdx, instance);
tlsInstance = std::make_unique<Tesselator>(bytes / 4);
}
Tesselator::Tesselator(int size)

View file

@ -34,13 +34,9 @@ private:
float xoo, yoo, zoo;
int _normal;
// 4J - added for thread local storage
public:
static void CreateNewThreadStorage(int bytes);
private:
static DWORD tlsIdx;
public:
static Tesselator *getInstance();
public:
static void CreateNewThreadStorage(int bytes);
static Tesselator *getInstance();
private:
bool tesselating;
@ -52,6 +48,7 @@ private:
int vboCounts;
int size;
public:
Tesselator(int size);
public:
Tesselator *getUniqueInstance(int size);

View file

@ -13,12 +13,6 @@
Region::~Region()
{
// flatChunksHeap automatically freed by unique_ptr
// AP - added a caching system for Chunk::rebuild to take advantage of
if( CachedTiles )
{
free(CachedTiles);
}
}
Region::Region(Level *level, int x1, int y1, int z1, int x2, int y2, int z2, int r)
@ -127,11 +121,11 @@ void Region::setCachedTiles(unsigned char *tiles, int xc, int zc)
xcCached = xc;
zcCached = zc;
int size = 16 * 16 * Level::maxBuildHeight;
if( CachedTiles == nullptr )
{
CachedTiles = static_cast<unsigned char *>(malloc(size));
}
memcpy(CachedTiles, tiles, size);
if (!CachedTiles)
{
CachedTiles = std::make_unique<unsigned char[]>(size);
}
std::copy(tiles, tiles + size, CachedTiles.get());
}
LevelChunk* Region::getLevelChunk(int x, int y, int z)

View file

@ -19,8 +19,8 @@ private:
bool allEmpty;
// AP - added a caching system for Chunk::rebuild to take advantage of
int xcCached, zcCached;
unsigned char *CachedTiles;
int xcCached, zcCached;
std::unique_ptr<unsigned char[]> CachedTiles;
public:
Region(Level *level, int x1, int y1, int z1, int x2, int y2, int z2, int r);