فهرست منبع

changes from az

Output now collates issues together into 1 entry for each leak point
tDictionary leak
marauder2k7 8 ماه پیش
والد
کامیت
b0eb3875c9
3فایلهای تغییر یافته به همراه95 افزوده شده و 28 حذف شده
  1. 14 14
      Engine/source/core/util/tDictionary.h
  2. 79 14
      Engine/source/platform/platformMemory.cpp
  3. 2 0
      Tools/CMake/torqueConfig.h.in

+ 14 - 14
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<typename Key, typename Value> HashTable<Key,Value>::HashTable() : mNodeAllocator(512)
 {
    mTableSize = 0;
-   mTable = 0;
+   mTable = nullptr;
    mSize = 0;
 }
 
@@ -328,7 +328,7 @@ template<typename Key, typename Value> HashTable<Key,Value>::HashTable(const Has
 {
    mSize = 0;
    mTableSize = 0;
-   mTable = 0;
+   mTable = nullptr;
    *this = p;
 }
 
@@ -357,7 +357,7 @@ typename HashTable<Key,Value>::Node* HashTable<Key,Value>::_next(U32 index) cons
    for (; index < mTableSize; index++)
       if (Node* node = mTable[index])
          return node;
-   return 0;
+   return nullptr;
 }
 
 template<typename Key, typename Value>
@@ -402,7 +402,7 @@ void HashTable<Key,Value>::_destroy()
       
    mNodeAllocator.freeBlocks();
    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>
 void HashTable<Key,Value>::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<Key,Value>::erase(const Key& key)
 template<typename Key, typename Value>
 void HashTable<Key,Value>::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<Key,Value>::erase(Iterator node)
 template<typename Key, typename Value>
 void HashTable<Key,Value>::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<Key,Value>::Iterator HashTable<Key,Value>::find(const Key& ke
       for (Node* itr = mTable[_index(key)]; itr; itr = itr->mNext)
          if ( KeyCmp::equals<Key>( itr->mPair.key, key ) )
             return Iterator(this,itr);
-   return Iterator(this,0);
+   return Iterator(this, nullptr);
 }
 
 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,0);
+   return ConstIterator(this, nullptr);
 }
 
 template<typename Key, typename Value>
@@ -659,13 +659,13 @@ inline typename HashTable<Key,Value>::ConstIterator HashTable<Key,Value>::begin(
 template<typename Key, typename Value>
 inline typename HashTable<Key,Value>::Iterator HashTable<Key,Value>::end()
 {
-   return Iterator(this,0);
+   return Iterator(this, nullptr);
 }
 
 template<typename Key, typename Value>
 inline typename HashTable<Key,Value>::ConstIterator HashTable<Key,Value>::end() const
 {
-   return ConstIterator(this,0);
+   return ConstIterator(this, nullptr);
 }
 
 

+ 79 - 14
Engine/source/platform/platformMemory.cpp

@@ -38,6 +38,7 @@
 #include <execinfo.h>
 #endif
 #include <ctime>
+#include <string>
 
 // 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

+ 2 - 0
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