Files
libsst/ZUtil/ZAlloc.cpp
2026-04-03 00:22:39 -05:00

289 lines
6.3 KiB
C++

#include <stdlib.h>
#include <string.h> /* memmove() */
#include <iostream>
#include <SST/SST_Concurrency.h>
#include <ZUtil/ZAlloc.hpp>
SST_Mutex AllocLock = SST_Concurrency_CreateMutex();
#if ZALLOC_CHECK_ALLOC
static ZAllocInfo* AllocList = NULL;
int ZAllocInfo::CurrentAllocCount = 0;
int ZAllocInfo::CurrentCheckpoint = 0;
void ZAllocAddTrack(uintptr_t _address, size_t _size, const char *_file, int _line, int _checkpoint)
{
ZAllocInfo *info = (ZAllocInfo*)malloc(sizeof(ZAllocInfo));
size_t len = strlen(_file);
info->Address = _address;
info->Size = _size;
if(len > sizeof(info->File)-1)
len = sizeof(info->File)-1;
memcpy(info->File, _file, len);
info->File[len] = '\0';
info->Line = _line;
info->Checkpoint = _checkpoint;
info->Next = NULL;
//Mutex may be NULL if doing pre-main() init
if (AllocLock)
SST_Concurrency_LockMutex(AllocLock);
info->Next = AllocList;
AllocList = info;
#if ZALLOC_EXTRA_SPAMMY
std::cerr << "Inc Alloc Count " << ZAllocInfo::CurrentAllocCount << " -> " << (ZAllocInfo::CurrentAllocCount+1) << std::endl;
#endif
ZAllocInfo::CurrentAllocCount++;
//Mutex may be NULL if doing pre-main() init
if (AllocLock)
SST_Concurrency_UnlockMutex(AllocLock);
}
void ZAllocRemoveTrack(uintptr_t _address)
{
//Mutex may be NULL if doing pre-main() init
if (AllocLock)
SST_Concurrency_LockMutex(AllocLock);
ZAllocInfo *prev = NULL;
ZAllocInfo *cur = AllocList;
while (cur != NULL)
{
if (cur->Address == _address)
{
if (prev == NULL) //i.e. removing head
AllocList = cur->Next;
else
prev->Next = cur->Next; //Remove "this" from the chain. link parent's next pointer to this one's next pointer so nobody has a reference to "this".
free(cur);
#if ZALLOC_EXTRA_SPAMMY
std::cerr << "Dec Alloc Count " << ZAllocInfo::CurrentAllocCount << " -> " << (ZAllocInfo::CurrentAllocCount-1) << std::endl;
#endif
ZAllocInfo::CurrentAllocCount--;
break;
}
prev = cur;
cur = cur->Next;
}
//Mutex may be NULL if doing pre-main() init
if (AllocLock)
SST_Concurrency_UnlockMutex(AllocLock);
}
void ZAllocDumpUnfreed(ZMemState *_state)
{
SST_Concurrency_LockMutex(AllocLock);
size_t totalSize = 0;
int checkpoint = _state == NULL ? 0 : _state->Checkpoint;
std::cerr << "--- ZAlloc Unfreed Memory Dump ---" << std::endl << std::endl;
std::cerr << ZAllocInfo::CurrentAllocCount << " Current Unfreed Allocations:" << std::endl;
ZAllocInfo *cur = AllocList;
while (cur != NULL)
{
if (cur->Checkpoint >= checkpoint)
{
std::cerr << cur->File << "\n\tLINE: " << cur->Line << "\n\tADDRESS " << (void*)cur->Address << " (" << cur->Size << " bytes) unfreed!" << std::endl;
totalSize += cur->Size;
}
cur = cur->Next;
}
std::cerr << "-----------------------------------------------------------\n";
std::cerr << "Total Unfreed: " << totalSize << " bytes" << std::endl << std::endl;
std::cerr << "--- End Unfreed Memory Dump ---" << std::endl;
SST_Concurrency_UnlockMutex(AllocLock);
}
//Debug Operator New
void * operator new(size_t _size, const char *_file, int _line, int _checkpoint)
throw()
{
void *ptr = (void*)malloc(_size);
ZAllocAddTrack((uintptr_t)ptr, _size, _file, _line, _checkpoint);
return ptr;
}
void * operator new[](size_t _size, const char* _file, int _line, int _checkpoint)
throw()
{
void *ptr = (void*)malloc(_size);
ZAllocAddTrack((uintptr_t)ptr, _size, _file, _line, _checkpoint);
return ptr;
}
//Debug Delete
void operator delete(void *_ptr, const char* _file, int _line, int _checkpoint)
{
(void)_file;
(void)_line;
(void)_checkpoint;
ZAllocRemoveTrack((uintptr_t)_ptr);
free(_ptr);
}
void operator delete[](void *_ptr, const char* _file, int _line, int _checkpoint)
{
(void)_file;
(void)_line;
(void)_checkpoint;
ZAllocRemoveTrack((uintptr_t)_ptr);
free(_ptr);
}
#ifndef __sun /* TODO: some error with Solaris Studio C++ compiler. */
void operator delete(void *_ptr)
{
ZAllocRemoveTrack((uintptr_t)_ptr);
free(_ptr);
}
void operator delete[](void *_ptr)
{
ZAllocRemoveTrack((uintptr_t)_ptr);
free(_ptr);
}
#endif
#endif
/////////////////////////////////////
/* Static New Functions and Fields */
/////////////////////////////////////
//This contains all our statically allocated pointers
void **StaticAllocArray = NULL;
//This is how many we can hold
int StaticAllocCapacity = 0;
//This is how many we've got
int StaticAllocSize = 0;
//This iterates and deletes
void ZAllocDeleteStatic(void)
{
int i;
//Mutex may be NULL if doing pre-main() init
if (AllocLock)
SST_Concurrency_LockMutex(AllocLock);
//Iterate, delete, then delete our static alloc array
for (i = 0; i < StaticAllocSize; i++)
free(StaticAllocArray[i]);
free(StaticAllocArray);
StaticAllocArray = NULL;
StaticAllocCapacity = 0;
StaticAllocSize = 0;
//Mutex may be NULL if doing pre-main() init
if (AllocLock)
SST_Concurrency_UnlockMutex(AllocLock);
}
void ZAllocAddStaticPtr(void *_ptr)
{
//Mutex may be NULL if doing pre-main() init
if (AllocLock)
SST_Concurrency_LockMutex(AllocLock);
//If we need to, register with atexit to call ZAllocDeleteStatic
if (StaticAllocArray == NULL)
atexit(ZAllocDeleteStatic);
//Check to see if StaticAllocArray is full
if (StaticAllocSize >= StaticAllocCapacity )
{
//Allocate new one
size_t newCapacity = StaticAllocCapacity == 0 ? 128 : StaticAllocCapacity * 2;
void *temp = malloc(newCapacity * sizeof(void*));
//Make sure we don't need to crash hard here
if (temp == NULL)
{
std::cerr << "ZAlloc failed to allocate static tracking array!" << std::endl;
exit(-1);
}
//Copy the old data in
memmove(temp, StaticAllocArray, StaticAllocSize * sizeof(void*));
//Free the old pointer
free(StaticAllocArray);
//Reset our pointer
StaticAllocArray = (void**)temp;
}
//Add new void*
StaticAllocArray[StaticAllocSize] = _ptr;
//Increment size
StaticAllocSize++;
//Mutex may be NULL if doing pre-main() init
if (AllocLock)
SST_Concurrency_UnlockMutex(AllocLock);
}
//Static operator new
void * operator new(size_t _size, znew_static_t _staticAlloc)
{
URFP(_staticAlloc);
void *ptr = (void*)malloc(_size);
ZAllocAddStaticPtr(ptr);
return ptr;
}
void * operator new[](size_t _size, znew_static_t _staticAlloc)
{
URFP(_staticAlloc);
void *ptr = (void*)malloc(_size);
ZAllocAddStaticPtr(ptr);
return ptr;
}