⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stackwalker.cpp

📁 奇迹世界公用文件源代码,研究网络游戏的朋友可以研究下
💻 CPP
📖 第 1 页 / 共 5 页
字号:
#endif


static void AllocHashInit(void) {

  memset(AllocHashTable, 0, sizeof(AllocHashTable));
  AllocHashEntries = 0;
  AllocHashCollisions = 0;
  AllocHashFreed = 0;
  AllocHashCurrentCount = 0;
  AllocHashMaxUsed = 0;

  AllocHashMaxCollisions = 0;
  AllocHashCurrentCollisions = 0;

#ifdef WITH_IMALLOC_SPY
  memset(IMallocHashTable, 0, sizeof(IMallocHashTable));
  IMallocHashEntries = 0;
  IMallocHashCollisions = 0;
  IMallocHashFreed = 0;
  IMallocHashCurrentCount = 0;
  IMallocHashMaxUsed = 0;

  IMallocHashMaxCollisions = 0;
  IMallocHashCurrentCollisions = 0;
#endif
  return;
}  // AllocHashInit


// AllocHashDeinit
// Returns the number of bytes, that are not freed (leaks)
static ULONG AllocHashDeinit(void) {
  ULONG ulRet = 0;
  BOOL bAppend = g_CallstackOutputType != ACOutput_XML;
  AllocCheckFileOpen(bAppend);  // open global log-file

  if (g_CallstackOutputType == ACOutput_XML)
  {
    _ftprintf(g_fFile, _T("<MEMREPORT "));
    WriteDateTime(g_fFile, TRUE);
    _ftprintf(g_fFile, _T(">\n"));
  }
  else
  {
    _ftprintf(g_fFile, _T("\n##### Memory Report ########################################\n"));
    WriteDateTime(g_fFile);
    _ftprintf(g_fFile, _T("\n"));
  }

#ifndef HASH_ENTRY_REMOVE_AT_FREE
  // output the used memory
  if (g_CallstackOutputType != ACOutput_XML)
    _ftprintf(g_fFile, _T("##### Memory used: #########################################\n"));
  AllocHashOut(g_fFile);
#endif

  // output the Memoty leaks
  if (g_CallstackOutputType != ACOutput_XML)
    _ftprintf(g_fFile, _T("\n##### Leaks: ###############################################\n"));
  ulRet = AllocHashOutLeaks(g_fFile);

  if (g_CallstackOutputType == ACOutput_Advanced)
  {
    // output some statistics from the hash-table
    _ftprintf(g_fFile, _T("***** Hash-Table statistics:\n"));
    _ftprintf(g_fFile, _T("      Table-Size:     %i\n"), ALLOC_HASH_ENTRIES);
    _ftprintf(g_fFile, _T("      Inserts:        %i\n"), AllocHashEntries);
    _ftprintf(g_fFile, _T("      Freed:          %i\n"), AllocHashFreed);
    _ftprintf(g_fFile, _T("      Sum Collisions: %i\n"), AllocHashCollisions);
    _ftprintf(g_fFile, _T("\n"));
    _ftprintf(g_fFile, _T("      Max used:       %i\n"), AllocHashMaxUsed);
    _ftprintf(g_fFile, _T("      Max Collisions: %i\n"), AllocHashMaxCollisions);
  }

  // Free Hash-Table
  ULONG ulTemp;
  AllocHashEntryType *pHashEntry = NULL;
  AllocHashEntryType *pHashEntryOld = NULL;

  // Now, free my own memory
  for(ulTemp = 0; ulTemp < ALLOC_HASH_ENTRIES; ulTemp++) {
    pHashEntry = &AllocHashTable[ulTemp];
    while(pHashEntry != NULL) {
      pHashEntryOld = pHashEntry;
      pHashEntry = pHashEntry->Next;
      if (pHashEntryOld != &AllocHashTable[ulTemp]) {
        // now free the dynamically allocated memory
        free(pHashEntryOld);
      }
    }  // while
  }  // for
  // empty the hash-table
  memset(AllocHashTable, 0, sizeof(AllocHashTable));

#ifdef WITH_IMALLOC_SPY
  // output the Memoty leaks
  if (g_CallstackOutputType != ACOutput_XML)
    _ftprintf(g_fFile, _T("\n##### COM-Leaks: ###############################################\n"));
  ulRet = IMallocHashOutLeaks(g_fFile);

  if (g_CallstackOutputType == ACOutput_Advanced)
  {
    // output some statistics from the hash-table
    _ftprintf(g_fFile, _T("***** Hash-Table statistics:\n"));
    _ftprintf(g_fFile, _T("      Table-Size:     %i\n"), ALLOC_HASH_ENTRIES);
    _ftprintf(g_fFile, _T("      Inserts:        %i\n"), IMallocHashEntries);
    _ftprintf(g_fFile, _T("      Freed:          %i\n"), IMallocHashFreed);
    _ftprintf(g_fFile, _T("      Sum Collisions: %i\n"), IMallocHashCollisions);
    _ftprintf(g_fFile, _T("\n"));
    _ftprintf(g_fFile, _T("      Max used:       %i\n"), IMallocHashMaxUsed);
    _ftprintf(g_fFile, _T("      Max Collisions: %i\n"), IMallocHashMaxCollisions);
  }

  // Free Hash-Table
  //ULONG ulTemp;
  IMallocHashEntryType *pIMHashEntry, *pIMHashEntryOld;

  // Gehe jeden Eintrag durch und gebe ihn frei
  for(ulTemp = 0; ulTemp < ALLOC_HASH_ENTRIES; ulTemp++) {
    pIMHashEntry = &IMallocHashTable[ulTemp];
    while(pHashEntry != NULL) {
      pIMHashEntryOld = pIMHashEntry;
      pIMHashEntry = pIMHashEntry->Next;
      if (pIMHashEntryOld != &IMallocHashTable[ulTemp]) {
        // es ist dynamischer Speicher, gebe ihn also frei:
        _free_dbg(pIMHashEntryOld, _CRT_BLOCK);
      }
    }  // while
  }  // for
  // L?che die gesamte Hash-Tabelle
  memset(IMallocHashTable, 0, sizeof(IMallocHashTable));
#endif


  if (g_CallstackOutputType == ACOutput_XML)
    _ftprintf(g_fFile, _T("</MEMREPORT>\n"));

  return ulRet;
}  // AllocHashDeinit

// AllocHashFunction
// The has-function (very simple)
static inline ULONG AllocHashFunction(long lRequestID) {
  // I couldn磘 find any better and faster
  return lRequestID % ALLOC_HASH_ENTRIES;
}  // AllocHashFunction

// AllocHashInsert
//   lRequestID: Key-Word (RequestID from AllocHook)
//   pContext:   Context-Record, for retrieving Callstack (EIP and EBP is only needed)
//   nDataSize:  How many bytes
static void AllocHashInsert(long lRequestID, CONTEXT &Context, size_t nDataSize) {
  ULONG HashIdx;
  AllocHashEntryType *pHashEntry;

  // change statistical data
  AllocHashEntries++;
  AllocHashCurrentCount++;
  if (AllocHashCurrentCount > AllocHashMaxUsed)
    AllocHashMaxUsed = AllocHashCurrentCount;

  // generate hash-value
  HashIdx = AllocHashFunction(lRequestID);

  pHashEntry = &AllocHashTable[HashIdx];
  if (pHashEntry->lRequestID == 0) {
    // Entry is empty...
  }
  else {
    // Entry is not empy! make a list of entries for this hash value...
    // change statistical data
    // if this happens often, you should increase the hah size or change the heash-function; 
    // to fasten the allocation time
    AllocHashCollisions++;
    AllocHashCurrentCollisions++;
    if (AllocHashCurrentCollisions > AllocHashMaxCollisions)
      AllocHashMaxCollisions = AllocHashCurrentCollisions;

    while(pHashEntry->Next != NULL) {
      pHashEntry = pHashEntry->Next;
    }

    pHashEntry->Next = (AllocHashEntryType*) calloc(sizeof(AllocHashEntryType), 1);
    pHashEntry = pHashEntry->Next;

  }
  pHashEntry->lRequestID = lRequestID;  // Key-Word
  pHashEntry->nDataSize = nDataSize;
  pHashEntry->Next = NULL;
  // Get EIP and save it in the record
  pHashEntry->dwEIPOffset = Context.Eip;
  if (ReadProcessMemory(GetCurrentProcess(), (LPCVOID) Context.Eip, &(pHashEntry->pcEIPAddr), MAX_EIP_LEN_BUF, &(pHashEntry->dwEIPLen)) == 0) {
    // Could not read memory... remove everything...
    memset(pHashEntry->pcEIPAddr, 0, MAX_EIP_LEN_BUF);
    pHashEntry->dwEIPLen = 0;
    pHashEntry->dwEIPOffset = 0;
  }

  // Get ESP and save it in the record
  pHashEntry->dwESPOffset = Context.Ebp;
  if (ReadProcessMemory(GetCurrentProcess(), (LPCVOID) Context.Ebp, &(pHashEntry->pcESPAddr), MAX_ESP_LEN_BUF, &(pHashEntry->dwESPLen)) == 0) {
    // Could not read memory... remove everything...
    memset(pHashEntry->pcESPAddr, 0, MAX_ESP_LEN_BUF);
    pHashEntry->dwESPLen = 0;
    pHashEntry->dwESPOffset = 0;

    // Check if I tried to read too much...
    if (GetLastError() == ERROR_PARTIAL_COPY)
    {
      // ask how many I can read:
      MEMORY_BASIC_INFORMATION MemBuffer;
      DWORD dwRet = VirtualQuery((LPCVOID) Context.Ebp, &MemBuffer, sizeof(MemBuffer));
      if (dwRet > 0)
      {
        // calculate the length
        DWORD len = ((DWORD) MemBuffer.BaseAddress + MemBuffer.RegionSize) - Context.Ebp;
        if ( (len > 0) && (len < MAX_ESP_LEN_BUF) )
        {
          // try to read it again (with the shorter length)
          if (ReadProcessMemory(GetCurrentProcess(), (LPCVOID) Context.Ebp, &(pHashEntry->pcESPAddr), len, &(pHashEntry->dwESPLen)) == 0)
          {
            // ok, now everything goes wrong... remove it...
            memset(pHashEntry->pcESPAddr, 0, MAX_ESP_LEN_BUF);
            pHashEntry->dwESPLen = 0;
            pHashEntry->dwESPOffset = 0;
          }
          else
          {
            pHashEntry->dwESPOffset = Context.Ebp;
          }
        }
      } // VirtualQuery was successfully
    }  // ERROR_PARTIAL_COPY
  }
}

// AllocHashFind
//   If ALLOC_ENTRY_NOT_FOUND is returned, the Key was not found!
//   If the Key was found, a pointer to the entry is returned
static AllocHashEntryType *AllocHashFind(long lRequestID) {
  ULONG HashIdx;
  AllocHashEntryType *pHashEntry;

  // get the Hash-Value
  HashIdx = AllocHashFunction(lRequestID);

  // Just do some simple checks:
  _ASSERTE(HashIdx < ALLOC_HASH_ENTRIES);

  pHashEntry = &AllocHashTable[HashIdx];
  while(pHashEntry != NULL) {
    if (pHashEntry->lRequestID == lRequestID) {
      return pHashEntry;
    }
    pHashEntry = pHashEntry->Next;
  }

  // entry was not found!
  return (AllocHashEntryType*) ALLOC_ENTRY_NOT_FOUND;
}  // AllocHashFind

// AllocHashRemove
//   Return: FALSE (0) : Key was found and removed/marked
//           TRUE (!=0): Key was not found
static BOOL AllocHashRemove(long lRequestID) {
  ULONG HashIdx;
  AllocHashEntryType *pHashEntry, *pHashEntryLast;

  // get the Hash-Value
  HashIdx = AllocHashFunction(lRequestID);

  // Just do some simple checks:
  _ASSERTE(HashIdx < ALLOC_HASH_ENTRIES);

  pHashEntryLast = NULL;
  pHashEntry = &AllocHashTable[HashIdx];
  while(pHashEntry != NULL) {
    if (pHashEntry->lRequestID == lRequestID) {
#ifdef HASH_ENTRY_REMOVE_AT_FREE
      AllocHashFreed++;
      AllocHashCurrentCount--;
      // release my memory
      if (pHashEntryLast == NULL) {
        // It is an entry in the table, so do not release this memory
        if (pHashEntry->Next == NULL) {
          // It was the last entry, so empty the table entry
          memset(&AllocHashTable[HashIdx], 0, sizeof(AllocHashTable[HashIdx]));
        }
        else {
          // There are some more entries, so shorten the list
          AllocHashEntryType *pTmp = pHashEntry->Next;
          *pHashEntry = *(pHashEntry->Next);
          free(pTmp);
        }
        return TRUE;
      }
      else {
        // now, I am in an dynamic allocated entry
        // it was a collision, so decrease the current collision count
        AllocHashCurrentCollisions--;
        pHashEntryLast->Next = pHashEntry->Next;
        free(pHashEntry);
        return TRUE;
      }
#else
      // increase the Remove-Count and let the objet stay in memory
      pHashEntry->cRemovedFlag++;
      return TRUE;
#endif
    }
    pHashEntryLast = pHashEntry;
    pHashEntry = pHashEntry->Next;
  }

  // if we are here, we could not find the RequestID
  return FALSE;
}

// ReadProcMemoryFromHash
//   Callback-Funtion for StackWalk for my own CallStack from the Hash-Table-Entries
static BOOL __stdcall ReadProcMemoryFromHash(HANDLE hRequestID, DWORD64 lpBaseAddress, PVOID lpBuffer, DWORD nSize, PDWORD lpNumberOfBytesRead) {
  // Try to find the RequestID
  AllocHashEntryType *pHashEntry;
  *lpNumberOfBytesRead = 0;

  pHashEntry = AllocHashFind((LONG) hRequestID);
  if (pHashEntry == (AllocHashEntryType*) ALLOC_ENTRY_NOT_FOUND) {
    // Not found, so I cannot return any memory
    *lpNumberOfBytesRead = 0;
    return FALSE;
  }
  if ( ((DWORD) lpBaseAddress >= pHashEntry->dwESPOffset) && ((DWORD) lpBaseAddress <= (pHashEntry->dwESPOffset+pHashEntry->dwESPLen)) ) {
    // Memory is located in ESP:
    // Calculate the offset
    DWORD dwOffset = (DWORD) lpBaseAddress - pHashEntry->dwESPOffset;
    DWORD dwSize = __min(nSize, MAX_ESP_LEN_BUF-dwOffset);
    memcpy(lpBuffer, &(pHashEntry->pcESPAddr[dwOffset]), dwSize);
    *lpNumberOfBytesRead = dwSize;
    if (dwSize != nSize)
      return FALSE;
  }

  if ( ((DWORD) lpBaseAddress >= pHashEntry->dwEIPOffset) && ((DWORD) lpBaseAddress <= (pHashEntry->dwEIPOffset+pHashEntry->dwEIPLen)) ) {
    // Memory is located in EIP:
    // Calculate the offset
    DWORD dwOffset = (DWORD) lpBaseAddress - pHashEntry->dwEIPOffset;
    DWORD dwSize = __min(nSize, MAX_ESP_LEN_BUF-dwOffset);
    memcpy(lpBuffer, &(pHashEntry->pcEIPAddr[dwOffset]), dwSize);
    *lpNumberOfBytesRead = dwSize;
    if (dwSize != nSize)
      return FALSE;
  }
  
  if (*lpNumberOfBytesRead == 0)  // Memory could not be found
    return FALSE;

  return TRUE;
}

// AllocHashOutLeaks
// Write all Memory (with callstack) which was not freed yet
//   Returns the number of bytes, that are not freed (leaks)
ULONG AllocHashOutLeaks(FILE *fFile) {
  ULONG ulTemp;
  AllocHashEntryType *pHashEntry;
  ULONG ulCount = 0;
  ULONG ulLeaksByte = 0;

  // Move throu every entry
  for(ulTemp = 0; ulTemp < ALLOC_HASH_ENTRIES; ulTemp++) {
    pHashEntry = &AllocHashTable[ulTemp];
    if (pHashEntry->lRequestID != 0) {
      while(pHashEntry != NULL) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -