mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-16 00:54:54 +00:00
changes from az
Output now collates issues together into 1 entry for each leak point tDictionary leak
This commit is contained in:
parent
1050cad372
commit
b0eb3875c9
3 changed files with 95 additions and 28 deletions
|
|
@ -193,7 +193,7 @@ private:
|
||||||
{
|
{
|
||||||
Node* mNext;
|
Node* mNext;
|
||||||
Pair mPair;
|
Pair mPair;
|
||||||
Node(): mNext(0) {}
|
Node(): mNext(nullptr) {}
|
||||||
Node(Pair p,Node* n)
|
Node(Pair p,Node* n)
|
||||||
: mNext(n),
|
: mNext(n),
|
||||||
mPair(p)
|
mPair(p)
|
||||||
|
|
@ -226,8 +226,8 @@ public:
|
||||||
|
|
||||||
_Iterator()
|
_Iterator()
|
||||||
{
|
{
|
||||||
mHashTable = 0;
|
mHashTable = nullptr;
|
||||||
mLink = 0;
|
mLink = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Iterator(M* table,E* ptr)
|
_Iterator(M* table,E* ptr)
|
||||||
|
|
@ -320,7 +320,7 @@ public:
|
||||||
template<typename Key, typename Value> HashTable<Key,Value>::HashTable() : mNodeAllocator(512)
|
template<typename Key, typename Value> HashTable<Key,Value>::HashTable() : mNodeAllocator(512)
|
||||||
{
|
{
|
||||||
mTableSize = 0;
|
mTableSize = 0;
|
||||||
mTable = 0;
|
mTable = nullptr;
|
||||||
mSize = 0;
|
mSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -328,7 +328,7 @@ template<typename Key, typename Value> HashTable<Key,Value>::HashTable(const Has
|
||||||
{
|
{
|
||||||
mSize = 0;
|
mSize = 0;
|
||||||
mTableSize = 0;
|
mTableSize = 0;
|
||||||
mTable = 0;
|
mTable = nullptr;
|
||||||
*this = p;
|
*this = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -357,7 +357,7 @@ typename HashTable<Key,Value>::Node* HashTable<Key,Value>::_next(U32 index) cons
|
||||||
for (; index < mTableSize; index++)
|
for (; index < mTableSize; index++)
|
||||||
if (Node* node = mTable[index])
|
if (Node* node = mTable[index])
|
||||||
return node;
|
return node;
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Key, typename Value>
|
template<typename Key, typename Value>
|
||||||
|
|
@ -402,7 +402,7 @@ void HashTable<Key,Value>::_destroy()
|
||||||
|
|
||||||
mNodeAllocator.freeBlocks();
|
mNodeAllocator.freeBlocks();
|
||||||
delete[] mTable;
|
delete[] mTable;
|
||||||
mTable = NULL;
|
mTable = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -509,7 +509,7 @@ typename HashTable<Key,Value>::Iterator HashTable<Key,Value>::insertEqual(const
|
||||||
template<typename Key, typename Value>
|
template<typename Key, typename Value>
|
||||||
void HashTable<Key,Value>::erase(const Key& key)
|
void HashTable<Key,Value>::erase(const Key& key)
|
||||||
{
|
{
|
||||||
if (mTable==NULL)
|
if (mTable == nullptr)
|
||||||
return;
|
return;
|
||||||
Node** prev = &mTable[_index(key)];
|
Node** prev = &mTable[_index(key)];
|
||||||
for (Node* itr = *prev; itr; prev = &itr->mNext, itr = itr->mNext)
|
for (Node* itr = *prev; itr; prev = &itr->mNext, itr = itr->mNext)
|
||||||
|
|
@ -529,7 +529,7 @@ void HashTable<Key,Value>::erase(const Key& key)
|
||||||
template<typename Key, typename Value>
|
template<typename Key, typename Value>
|
||||||
void HashTable<Key,Value>::erase(Iterator node)
|
void HashTable<Key,Value>::erase(Iterator node)
|
||||||
{
|
{
|
||||||
if (mTable==NULL)
|
if (mTable == nullptr)
|
||||||
return;
|
return;
|
||||||
Node** prev = &mTable[_index(node->key)];
|
Node** prev = &mTable[_index(node->key)];
|
||||||
for (Node* itr = *prev; itr; prev = &itr->mNext, itr = itr->mNext)
|
for (Node* itr = *prev; itr; prev = &itr->mNext, itr = itr->mNext)
|
||||||
|
|
@ -547,7 +547,7 @@ void HashTable<Key,Value>::erase(Iterator node)
|
||||||
template<typename Key, typename Value>
|
template<typename Key, typename Value>
|
||||||
void HashTable<Key,Value>::erase(const Key & key, const Value & value)
|
void HashTable<Key,Value>::erase(const Key & key, const Value & value)
|
||||||
{
|
{
|
||||||
if (mTable==NULL)
|
if (mTable == nullptr)
|
||||||
return;
|
return;
|
||||||
Node** prev = &mTable[_index(key)];
|
Node** prev = &mTable[_index(key)];
|
||||||
for (Node* itr = *prev; itr; prev = &itr->mNext, itr = itr->mNext)
|
for (Node* itr = *prev; itr; prev = &itr->mNext, itr = itr->mNext)
|
||||||
|
|
@ -591,7 +591,7 @@ typename HashTable<Key,Value>::Iterator HashTable<Key,Value>::find(const Key& ke
|
||||||
for (Node* itr = mTable[_index(key)]; itr; itr = itr->mNext)
|
for (Node* itr = mTable[_index(key)]; itr; itr = itr->mNext)
|
||||||
if ( KeyCmp::equals<Key>( itr->mPair.key, key ) )
|
if ( KeyCmp::equals<Key>( itr->mPair.key, key ) )
|
||||||
return Iterator(this,itr);
|
return Iterator(this,itr);
|
||||||
return Iterator(this,0);
|
return Iterator(this, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Key, typename Value>
|
template<typename Key, typename Value>
|
||||||
|
|
@ -605,7 +605,7 @@ typename HashTable<Key,Value>::ConstIterator HashTable<Key,Value>::find(const Ke
|
||||||
return ConstIterator(this,itr);
|
return ConstIterator(this,itr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ConstIterator(this,0);
|
return ConstIterator(this, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Key, typename Value>
|
template<typename Key, typename Value>
|
||||||
|
|
@ -659,13 +659,13 @@ inline typename HashTable<Key,Value>::ConstIterator HashTable<Key,Value>::begin(
|
||||||
template<typename Key, typename Value>
|
template<typename Key, typename Value>
|
||||||
inline typename HashTable<Key,Value>::Iterator HashTable<Key,Value>::end()
|
inline typename HashTable<Key,Value>::Iterator HashTable<Key,Value>::end()
|
||||||
{
|
{
|
||||||
return Iterator(this,0);
|
return Iterator(this, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Key, typename Value>
|
template<typename Key, typename Value>
|
||||||
inline typename HashTable<Key,Value>::ConstIterator HashTable<Key,Value>::end() const
|
inline typename HashTable<Key,Value>::ConstIterator HashTable<Key,Value>::end() const
|
||||||
{
|
{
|
||||||
return ConstIterator(this,0);
|
return ConstIterator(this, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
#endif
|
#endif
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
// If profile paths are enabled, disable profiling of the
|
// If profile paths are enabled, disable profiling of the
|
||||||
// memory manager as that would cause a cyclic dependency
|
// memory manager as that would cause a cyclic dependency
|
||||||
|
|
@ -75,7 +76,16 @@ namespace Memory
|
||||||
static U32 currentAllocId = 0;
|
static U32 currentAllocId = 0;
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
char gLogFilename[256] = { 0 };
|
char gLogFilename[256] = { 0 };
|
||||||
bool gStackTrace = false;
|
bool gStackTrace = true;
|
||||||
|
bool gFromScript = false;
|
||||||
|
|
||||||
|
struct memReport
|
||||||
|
{
|
||||||
|
std::string report;
|
||||||
|
bool skip;
|
||||||
|
U32 count = 1;
|
||||||
|
U32 total = 0;
|
||||||
|
} memLog[MaxAllocs];
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
|
|
@ -100,16 +110,27 @@ namespace Memory
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::fprintf(log, "\n--- Memory Leak Report ---\n");
|
std::fprintf(log, "\n--- Memory Leak Report ---\n");
|
||||||
for (U32 i = 0; i < allocCount; ++i)
|
|
||||||
|
U32 start = 0;
|
||||||
|
U32 stop = allocCount;
|
||||||
|
if (gFromScript) //filter out the bits from console
|
||||||
{
|
{
|
||||||
if (allocList[i].ptr != nullptr)
|
start = 6;
|
||||||
|
stop = allocCount - 8;
|
||||||
|
}
|
||||||
|
for (U32 curRep = start; curRep < stop; ++curRep)
|
||||||
|
{
|
||||||
|
if (allocList[curRep].ptr != nullptr)
|
||||||
{
|
{
|
||||||
std::fprintf(log, "Leak: %p (%zu bytes) from %s:%u [id=%u]\n",
|
char entry[512] = "";
|
||||||
allocList[i].ptr, allocList[i].size,
|
std::sprintf(entry, "from %s:%u\n", allocList[curRep].file ? allocList[curRep].file : "(null)", allocList[curRep].line);
|
||||||
allocList[i].file ? allocList[i].file : "(null)", allocList[i].line,
|
|
||||||
allocList[i].allocId);
|
memLog[curRep].skip = false;
|
||||||
|
std::string report = entry;
|
||||||
|
|
||||||
if (gStackTrace)
|
if (gStackTrace)
|
||||||
{
|
{
|
||||||
|
char stack[512] = "";
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
SYMBOL_INFO* symbol = (SYMBOL_INFO*)malloc(sizeof(SYMBOL_INFO) + 256);
|
SYMBOL_INFO* symbol = (SYMBOL_INFO*)malloc(sizeof(SYMBOL_INFO) + 256);
|
||||||
symbol->MaxNameLen = 255;
|
symbol->MaxNameLen = 255;
|
||||||
|
|
@ -118,31 +139,67 @@ namespace Memory
|
||||||
HANDLE process = GetCurrentProcess();
|
HANDLE process = GetCurrentProcess();
|
||||||
SymInitialize(process, NULL, TRUE);
|
SymInitialize(process, NULL, TRUE);
|
||||||
|
|
||||||
for (int j = 0; j < allocList[i].backtraceSize; ++j)
|
for (int curStack = 0; curStack < allocList[curRep].backtraceSize; ++curStack)
|
||||||
{
|
{
|
||||||
DWORD64 addr = (DWORD64)(allocList[i].backtracePtrs[j]);
|
DWORD64 addr = (DWORD64)(allocList[curRep].backtracePtrs[curStack]);
|
||||||
if (SymFromAddr(process, addr, 0, symbol))
|
if (SymFromAddr(process, addr, 0, symbol))
|
||||||
{
|
{
|
||||||
std::fprintf(log, " [%d] %s - 0x%0llX\n", j, symbol->Name, symbol->Address);
|
std::sprintf(stack, " [%d] %s - 0x%0llX\n", curStack, symbol->Name, symbol->Address);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::fprintf(log, " [%d] ??? - 0x%0llX\n", j, addr);
|
std::sprintf(stack, " [%d] ??? - 0x%0llX\n", curStack, addr);
|
||||||
}
|
}
|
||||||
|
report += stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::free(symbol);
|
std::free(symbol);
|
||||||
#else
|
#else
|
||||||
char** symbols = backtrace_symbols(allocList[i].backtracePtrs, allocList[i].backtraceSize);
|
char** symbols = backtrace_symbols(allocList[curRep].backtracePtrs, allocList[i].backtraceSize);
|
||||||
for (int j = 0; j < allocList[i].backtraceSize; ++j)
|
for (int curStack = 0; curStack < allocList[curRep].backtraceSize; ++curStack)
|
||||||
{
|
{
|
||||||
std::fprintf(log, " [%d] %s\n", j, symbols[j]);
|
std::sprintf(stack, " [%d] %s\n", curStack, symbols[curStack]);
|
||||||
|
report += stack;
|
||||||
}
|
}
|
||||||
std::free(symbols);
|
std::free(symbols);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (report.find("getDocsLink") != std::string::npos)
|
||||||
|
{
|
||||||
|
//known issue. one off allocation
|
||||||
|
memLog[curRep].skip = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (U32 oldRep = start; oldRep < curRep; ++oldRep)
|
||||||
|
{
|
||||||
|
if (!memLog[oldRep].skip && (memLog[oldRep].report.find(report) != std::string::npos))
|
||||||
|
{
|
||||||
|
//inc origional
|
||||||
|
memLog[oldRep].count++;
|
||||||
|
memLog[oldRep].total += allocList[curRep].size;
|
||||||
|
//skip dupe report
|
||||||
|
memLog[curRep].skip = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!memLog[curRep].skip)
|
||||||
|
{
|
||||||
|
memLog[curRep].report = report;
|
||||||
|
memLog[curRep].count = 1;
|
||||||
|
memLog[curRep].total = allocList[curRep].size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (U32 ntry = start; ntry < stop; ++ntry)
|
||||||
|
{
|
||||||
|
if (!memLog[ntry].skip)
|
||||||
|
{
|
||||||
|
std::fprintf(log, "Leak-count[%i]total[%i]:%s", memLog[ntry].count, memLog[ntry].total, memLog[ntry].report.c_str());
|
||||||
|
memLog[ntry].report.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::fclose(log);
|
std::fclose(log);
|
||||||
initialized = false;
|
initialized = false;
|
||||||
}
|
}
|
||||||
|
|
@ -341,6 +398,14 @@ void* dRealloc_r(void* in_pResize, dsize_t in_size, const char* fileName, const
|
||||||
return Memory::realloc(in_pResize, in_size, fileName, line);
|
return Memory::realloc(in_pResize, in_size, fileName, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DefineEngineFunction(LeakTrace, void, (bool start, bool stackTrace), (true, true), "start/stop tracing leaks")
|
||||||
|
{
|
||||||
|
if (Memory::initialized) Memory::shutdown();
|
||||||
|
if (start) Memory::init();
|
||||||
|
Memory::gFromScript = true;
|
||||||
|
Memory::gStackTrace = stackTrace;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// Don't manage our own memory
|
// Don't manage our own memory
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,9 @@
|
||||||
#cmakedefine TORQUE_MULTITHREAD
|
#cmakedefine TORQUE_MULTITHREAD
|
||||||
|
|
||||||
/// Define me if you want to disable Torque memory manager.
|
/// Define me if you want to disable Torque memory manager.
|
||||||
|
#ifndef TORQUE_ENABLE_ASSERTS
|
||||||
#cmakedefine TORQUE_DISABLE_MEMORY_MANAGER
|
#cmakedefine TORQUE_DISABLE_MEMORY_MANAGER
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Define me if you want to disable the virtual mount system.
|
/// Define me if you want to disable the virtual mount system.
|
||||||
#cmakedefine TORQUE_DISABLE_VIRTUAL_MOUNT_SYSTEM
|
#cmakedefine TORQUE_DISABLE_VIRTUAL_MOUNT_SYSTEM
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue