diff --git a/Engine/source/core/util/tDictionary.h b/Engine/source/core/util/tDictionary.h index 4af0d6037..6c8c7d21f 100644 --- a/Engine/source/core/util/tDictionary.h +++ b/Engine/source/core/util/tDictionary.h @@ -193,7 +193,7 @@ private: { Node* mNext; Pair mPair; - Node(): mNext(0) {} + Node(): mNext(nullptr) {} Node(Pair p,Node* n) : mNext(n), mPair(p) @@ -226,8 +226,8 @@ public: _Iterator() { - mHashTable = 0; - mLink = 0; + mHashTable = nullptr; + mLink = nullptr; } _Iterator(M* table,E* ptr) @@ -320,7 +320,7 @@ public: template HashTable::HashTable() : mNodeAllocator(512) { mTableSize = 0; - mTable = 0; + mTable = nullptr; mSize = 0; } @@ -328,7 +328,7 @@ template HashTable::HashTable(const Has { mSize = 0; mTableSize = 0; - mTable = 0; + mTable = nullptr; *this = p; } @@ -357,7 +357,7 @@ typename HashTable::Node* HashTable::_next(U32 index) cons for (; index < mTableSize; index++) if (Node* node = mTable[index]) return node; - return 0; + return nullptr; } template @@ -402,7 +402,7 @@ void HashTable::_destroy() mNodeAllocator.freeBlocks(); delete[] mTable; - mTable = NULL; + mTable = nullptr; } @@ -509,7 +509,7 @@ typename HashTable::Iterator HashTable::insertEqual(const template void HashTable::erase(const Key& key) { - if (mTable==NULL) + if (mTable == nullptr) return; Node** prev = &mTable[_index(key)]; for (Node* itr = *prev; itr; prev = &itr->mNext, itr = itr->mNext) @@ -529,7 +529,7 @@ void HashTable::erase(const Key& key) template void HashTable::erase(Iterator node) { - if (mTable==NULL) + if (mTable == nullptr) return; Node** prev = &mTable[_index(node->key)]; for (Node* itr = *prev; itr; prev = &itr->mNext, itr = itr->mNext) @@ -547,7 +547,7 @@ void HashTable::erase(Iterator node) template void HashTable::erase(const Key & key, const Value & value) { - if (mTable==NULL) + if (mTable == nullptr) return; Node** prev = &mTable[_index(key)]; for (Node* itr = *prev; itr; prev = &itr->mNext, itr = itr->mNext) @@ -591,7 +591,7 @@ typename HashTable::Iterator HashTable::find(const Key& ke for (Node* itr = mTable[_index(key)]; itr; itr = itr->mNext) if ( KeyCmp::equals( itr->mPair.key, key ) ) return Iterator(this,itr); - return Iterator(this,0); + return Iterator(this, nullptr); } template @@ -605,7 +605,7 @@ typename HashTable::ConstIterator HashTable::find(const Ke return ConstIterator(this,itr); } } - return ConstIterator(this,0); + return ConstIterator(this, nullptr); } template @@ -659,13 +659,13 @@ inline typename HashTable::ConstIterator HashTable::begin( template inline typename HashTable::Iterator HashTable::end() { - return Iterator(this,0); + return Iterator(this, nullptr); } template inline typename HashTable::ConstIterator HashTable::end() const { - return ConstIterator(this,0); + return ConstIterator(this, nullptr); } diff --git a/Engine/source/platform/platformMemory.cpp b/Engine/source/platform/platformMemory.cpp index 6bc2b0447..fe732db52 100644 --- a/Engine/source/platform/platformMemory.cpp +++ b/Engine/source/platform/platformMemory.cpp @@ -38,6 +38,7 @@ #include #endif #include +#include // If profile paths are enabled, disable profiling of the // memory manager as that would cause a cyclic dependency @@ -75,7 +76,16 @@ namespace Memory static U32 currentAllocId = 0; static bool initialized = false; 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() { @@ -100,16 +110,27 @@ namespace Memory return; 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", - allocList[i].ptr, allocList[i].size, - allocList[i].file ? allocList[i].file : "(null)", allocList[i].line, - allocList[i].allocId); + char entry[512] = ""; + std::sprintf(entry, "from %s:%u\n", allocList[curRep].file ? allocList[curRep].file : "(null)", allocList[curRep].line); + + memLog[curRep].skip = false; + std::string report = entry; + if (gStackTrace) { + char stack[512] = ""; #ifdef _WIN32 SYMBOL_INFO* symbol = (SYMBOL_INFO*)malloc(sizeof(SYMBOL_INFO) + 256); symbol->MaxNameLen = 255; @@ -118,31 +139,67 @@ namespace Memory HANDLE process = GetCurrentProcess(); 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)) { - 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 { - std::fprintf(log, " [%d] ??? - 0x%0llX\n", j, addr); + std::sprintf(stack, " [%d] ??? - 0x%0llX\n", curStack, addr); } + report += stack; } std::free(symbol); #else - char** symbols = backtrace_symbols(allocList[i].backtracePtrs, allocList[i].backtraceSize); - for (int j = 0; j < allocList[i].backtraceSize; ++j) + char** symbols = backtrace_symbols(allocList[curRep].backtracePtrs, allocList[i].backtraceSize); + 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); #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); 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); } +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 // Don't manage our own memory diff --git a/Tools/CMake/torqueConfig.h.in b/Tools/CMake/torqueConfig.h.in index 717c05eb1..a0bbc70a8 100644 --- a/Tools/CMake/torqueConfig.h.in +++ b/Tools/CMake/torqueConfig.h.in @@ -54,7 +54,9 @@ #cmakedefine TORQUE_MULTITHREAD /// Define me if you want to disable Torque memory manager. +#ifndef TORQUE_ENABLE_ASSERTS #cmakedefine TORQUE_DISABLE_MEMORY_MANAGER +#endif /// Define me if you want to disable the virtual mount system. #cmakedefine TORQUE_DISABLE_VIRTUAL_MOUNT_SYSTEM