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

📄 stackwalker.cpp

📁 奇迹世界公用文件源代码,研究网络游戏的朋友可以研究下
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/*////////////////////////////////////////////////////////////////////////////
 *  Project:
 *    Memory_and_Exception_Trace
 *
 * ///////////////////////////////////////////////////////////////////////////
 *	File:
 *		Stackwalker.cpp
 *
 *	Remarks:
 *    Dumps memory leaks (unreleased allocations) for CRT-Allocs and COM-Allocs
 *    Dumps the stack of an thread if an exepction occurs
 *
 *  Known bugs:
 *    - If the allocation-RequestID wrap, then allocations will get lost...
 *
 *	Author:
 *		Jochen Kalmbach, Germany
 *    (c) 2002-2003 (Freeware)
 *    http://www.codeproject.com/tools/leakfinder.asp
 * 
 * License (The zlib/libpng License, http://www.opensource.org/licenses/zlib-license.php):
 *
 * Copyright (c) 2003 Jochen Kalmbach
 *
 * This software is provided 'as-is', without any express or implied warranty. 
 * In no event will the authors be held liable for any damages arising from the 
 * use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose, including 
 * commercial applications, and to alter it and redistribute it freely, subject to 
 * the following restrictions:
 * 
 * 1. The origin of this software must not be misrepresented; you must not claim 
 *    that you wrote the original software. If you use this software in a product, 
 *    an acknowledgment in the product documentation would be appreciated but is 
 *    not required.
 *
 * 2. Altered source versions must be plainly marked as such, and must not be 
 *    misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source distribution.
 *
 *//////////////////////////////////////////////////////////////////////////////

//#include "stdafx.h"  // should be uncommented for precompiled headers

#include "UtilityCommon.h"
#include <windows.h>
#include <string>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <crtdbg.h>
#include <tchar.h>

#include "Stackwalker.h"

// If the following is defined, only the used memories are stored in the hash-table. 
// If the memory is freed, it will be removed from the hash-table (to reduce memory)
// Consequences: At DeInitAllocHook, only Leaks will be reported
#define HASH_ENTRY_REMOVE_AT_FREE


// 0 = Do not write any output during runtime-alloc-call
// 1 = Write only the alloc action (malloc, realloc, free)
// 2 = Write alloc action and callstack only for malloc/realloc
// 3 = Write alloc action and callstack for all actions
static ULONG g_ulShowStackAtAlloc = 0;

// the form of the output file
static eAllocCheckOutput g_CallstackOutputType = ACOutput_Simple;


// Size of Hash-Table (this should be a prime number to avoid collisions)
#define ALLOC_HASH_ENTRIES 1023


// Size of Callstack-trace in bytes (0x500 => appr. 5-9 functions, depending on parameter count for each function)
#define MAX_ESP_LEN_BUF 0x500


// Normally we can ignore allocations from the Runtime-System
#define IGNORE_CRT_ALLOC

// MaxSize: 1 MByte (only for StackwalkFilter)
#define LOG_FILE_MAX_SIZE 1024*1024

// If the following is defined, then COM-Leaks will also be tracked
#define WITH_IMALLOC_SPY

// #############################################################################################
#ifdef WITH_IMALLOC_SPY
//forwards:
void IMallocHashInsert(void *pData, CONTEXT &Context, size_t nDataSize);
BOOL IMallocHashRemove(void *pData);


#pragma warning (push)
#pragma warning (disable: 4100)


// IMallocSpy-Interface
class CMallocSpy : public IMallocSpy
{
public:
  CMallocSpy(void) {
    m_cbRequest = 0;
  }
  ~CMallocSpy(void) {
  }
  // IUnknown methods
  STDMETHOD(QueryInterface) (REFIID riid, LPVOID *ppUnk) {
    HRESULT hr = S_OK;
    if (IsEqualIID(riid, IID_IUnknown)) {
        *ppUnk = (IUnknown *) this;
    }
    else if (IsEqualIID(riid, IID_IMallocSpy)) {
        *ppUnk =  (IMalloc *) this;
    }
    else {
        *ppUnk = NULL;
        hr =  E_NOINTERFACE;
    }
    AddRef();
    return hr;
  }
  STDMETHOD_(ULONG, AddRef) (void) {
    return InterlockedIncrement(&m_cRef);
  }
  STDMETHOD_(ULONG, Release) (void) {
    LONG cRef;
    cRef = InterlockedDecrement(&m_cRef);
    if (cRef == 0)
    {
      delete this;
    }
    return cRef;
  }
  // IMallocSpy methods
  STDMETHOD_(ULONG, PreAlloc) (ULONG cbRequest) {
    m_cbRequest = cbRequest;
    return cbRequest;
  }
  STDMETHOD_(void *, PostAlloc) (void *pActual) {
    HANDLE hThread;
    if (DuplicateHandle( GetCurrentProcess(), GetCurrentThread(),
      GetCurrentProcess(), &hThread, 0, false, DUPLICATE_SAME_ACCESS ) != 0) {
      // Ok
      CONTEXT c;
      memset( &c, '\0', sizeof c );
      c.ContextFlags = CONTEXT_FULL;
      if ( GetThreadContext( hThread, &c )  != 0) {
        // Ok
        IMallocHashInsert(pActual, c, m_cbRequest);
      }
      CloseHandle(hThread);
    }
    return pActual;
  }
  STDMETHOD_(void *, PreFree) (void *pRequest, BOOL fSpyed) {
    IMallocHashRemove(pRequest);
    return pRequest;
  }
  STDMETHOD_(void, PostFree) (BOOL fSpyed) {
    return;
  }
  STDMETHOD_(ULONG, PreRealloc) (void *pRequest, ULONG cbRequest,
    void **ppNewRequest, BOOL fSpyed) {
    IMallocHashRemove(pRequest);
    m_cbRequest = cbRequest;
    *ppNewRequest = pRequest;  // Bug fixed. Thanx to Christoph Weber
    return cbRequest;
  }
  STDMETHOD_(void *, PostRealloc) (void *pActual, BOOL fSpyed) {
    HANDLE hThread;
    if (DuplicateHandle( GetCurrentProcess(), GetCurrentThread(),
      GetCurrentProcess(), &hThread, 0, false, DUPLICATE_SAME_ACCESS ) != 0) {
      // Ok
      CONTEXT c;
      memset( &c, '\0', sizeof c );
      c.ContextFlags = CONTEXT_FULL;
      if ( GetThreadContext( hThread, &c )  != 0) {
        // Ok
        IMallocHashInsert(pActual, c, m_cbRequest);
      }
      CloseHandle(hThread);
    }
    return pActual;
  }
  STDMETHOD_(void *, PreGetSize) (void *pRequest, BOOL fSpyed) {
    return pRequest;
  }
  STDMETHOD_(ULONG, PostGetSize) (ULONG cbActual, BOOL fSpyed) {
    return cbActual;
  }
  STDMETHOD_(void *, PreDidAlloc) (void *pRequest, BOOL fSpyed) {
    return pRequest;
  }
  STDMETHOD_(BOOL, PostDidAlloc) (void *pRequest, BOOL fSpyed, BOOL fActual) {
    return fActual;
  }
  STDMETHOD_(void, PreHeapMinimize) (void) {
    return;
  }
  STDMETHOD_(void, PostHeapMinimize) (void) {
    return;
  }
private:
  LONG    m_cRef;
  ULONG m_cbRequest;
};
#endif

// #############################################################################################
// Here I have included the API-Version 9 declarations, so it will also compile on systems, where the new PSDK is not installed
// Normally we just need to include the "dbghelp.h" file
#include <imagehlp.h>
#if API_VERSION_NUMBER < 9
typedef
BOOL
(__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(
    HANDLE      hProcess,
    DWORD64     qwBaseAddress,
    PVOID       lpBuffer,
    DWORD       nSize,
    LPDWORD     lpNumberOfBytesRead
    );

typedef struct _IMAGEHLP_LINE64 {
    DWORD                       SizeOfStruct;           // set to sizeof(IMAGEHLP_LINE64)
    PVOID                       Key;                    // internal
    DWORD                       LineNumber;             // line number in file
    PCHAR                       FileName;               // full filename
    DWORD64                     Address;                // first instruction of line
} IMAGEHLP_LINE64, *PIMAGEHLP_LINE64;


typedef struct _IMAGEHLP_MODULE64 {
    DWORD                       SizeOfStruct;           // set to sizeof(IMAGEHLP_MODULE64)
    DWORD64                     BaseOfImage;            // base load address of module
    DWORD                       ImageSize;              // virtual size of the loaded module
    DWORD                       TimeDateStamp;          // date/time stamp from pe header
    DWORD                       CheckSum;               // checksum from the pe header
    DWORD                       NumSyms;                // number of symbols in the symbol table
    SYM_TYPE                    SymType;                // type of symbols loaded
    CHAR                        ModuleName[32];         // module name
    CHAR                        ImageName[256];         // image name
    CHAR                        LoadedImageName[256];   // symbol file name
} IMAGEHLP_MODULE64, *PIMAGEHLP_MODULE64;

typedef struct _IMAGEHLP_SYMBOL64 {
    DWORD                       SizeOfStruct;           // set to sizeof(IMAGEHLP_SYMBOL64)
    DWORD64                     Address;                // virtual address including dll base address
    DWORD                       Size;                   // estimated size of symbol, can be zero
    DWORD                       Flags;                  // info about the symbols, see the SYMF defines
    DWORD                       MaxNameLength;          // maximum size of symbol name in 'Name'
    CHAR                        Name[1];                // symbol name (null terminated string)
} IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64;

typedef struct _tagADDRESS64 {
    DWORD64       Offset;
    WORD          Segment;
    ADDRESS_MODE  Mode;
} ADDRESS64, *LPADDRESS64;

typedef struct _KDHELP64 {

    //
    // address of kernel thread object, as provided in the
    // WAIT_STATE_CHANGE packet.
    //
    DWORD64   Thread;

    //
    // offset in thread object to pointer to the current callback frame
    // in kernel stack.
    //
    DWORD   ThCallbackStack;

    //
    // offset in thread object to pointer to the current callback backing
    // store frame in kernel stack.
    //
    DWORD   ThCallbackBStore;

    //
    // offsets to values in frame:
    //
    // address of next callback frame
    DWORD   NextCallback;

    // address of saved frame pointer (if applicable)
    DWORD   FramePointer;


    //
    // Address of the kernel function that calls out to user mode
    //
    DWORD64   KiCallUserMode;

    //
    // Address of the user mode dispatcher function
    //
    DWORD64   KeUserCallbackDispatcher;

    //
    // Lowest kernel mode address
    //
    DWORD64   SystemRangeStart;

    DWORD64  Reserved[8];

} KDHELP64, *PKDHELP64;


typedef struct _tagSTACKFRAME64 {
    ADDRESS64   AddrPC;               // program counter
    ADDRESS64   AddrReturn;           // return address
    ADDRESS64   AddrFrame;            // frame pointer
    ADDRESS64   AddrStack;            // stack pointer
    ADDRESS64   AddrBStore;           // backing store pointer
    PVOID       FuncTableEntry;       // pointer to pdata/fpo or NULL
    DWORD64     Params[4];            // possible arguments to the function
    BOOL        Far;                  // WOW far call
    BOOL        Virtual;              // is this a virtual frame?
    DWORD64     Reserved[3];
    KDHELP64    KdHelp;
} STACKFRAME64, *LPSTACKFRAME64;

typedef
PVOID
(__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)(
    HANDLE  hProcess,
    DWORD64 AddrBase
    );

typedef
DWORD64
(__stdcall *PGET_MODULE_BASE_ROUTINE64)(
    HANDLE  hProcess,
    DWORD64 Address
    );

typedef
DWORD64
(__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(
    HANDLE    hProcess,
    HANDLE    hThread,
    LPADDRESS64 lpaddr
    );
#endif
// #############################################################################################



// Forward definitions of functions:
static void ShowStackRM( HANDLE hThread, CONTEXT& c, FILE *fLogFile, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryFunction, HANDLE hProcess);
static void ShowStack( HANDLE hThread, CONTEXT& c, FILE *fLogFile);

#ifndef HASH_ENTRY_REMOVE_AT_FREE
	static void AllocHashOut(FILE*);
#endif
static ULONG AllocHashOutLeaks(FILE*);



// Globale Vars:
static TCHAR *g_pszAllocLogName = NULL;
static FILE *g_fFile = NULL;

// AllocCheckFileOpen
//  Checks if the log-file is already opened
//  if not, try to open file (append or create if not exists)

⌨️ 快捷键说明

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