#pragma once
#include
#include
#define CRTDBG_MAP_ALLOC
#include
#include
#include
typedef enum _THREADINFOCLASS {
ThreadBasicInformation,
ThreadTimes,
ThreadPriority,
ThreadBasePriority,
ThreadAffinityMask,
ThreadImpersonationToken,
ThreadDescriptorTableEntry,
ThreadEnableAlignmentFaultFixup,
ThreadEventPair_Reusable,
ThreadQuerySetWin32StartAddress,
ThreadZeroTlsCell,
ThreadPerformanceCount,
ThreadAmILastThread,
ThreadIdealProcessor,
ThreadPriorityBoost,
ThreadSetTlsArrayAddress,
ThreadIsIoPending,
ThreadHideFromDebugger,
ThreadBreakOnTermination,
MaxThreadInfoClass
}THREADINFOCLASS;
typedef struct _CLIENT_ID {
HANDLE UniqueProcess;
HANDLE UniqueThread;
}CLIENT_ID;
typedef struct _THREAD_BASIC_INFORMATION {
LONG ExitStatus;
PVOID TebBaseAddress;
CLIENT_ID ClientId;
LONG AffinityMask;
LONG Priority;
LONG BasePriority;
}THREAD_BASIC_INFORMATION, * PTHREAD_BASIC_INFORMATION;
using ZwQueryInformationThread= LONG(__stdcall * )(
IN HANDLE ThreadHandle,
IN THREADINFOCLASS ThreadInformationClass,
OUT PVOID ThreadInformation,
IN ULONG ThreadInformationLength,
OUT PULONG ReturnLength OPTIONAL
) ;
#ifdef _DEBUG
#define DBG_NEW new ( _CLIENT_BLOCK , __FILE__ , __LINE__ )
#define new DBG_NEW
#else
#define DBG_NEW new
#endif
#define KB 1024
#define MB (KB*KB)
#define MEMINIFILENAME "memConfig.ini"
typedef struct _HOOK_PRO_FILE
{
BOOL bViewBlock;
BOOL bClientHook;
BOOL bAllocHook;
size_t nMemlimit;
HANDLE hLogFile;
TCHAR szlogfilename[MAX_PATH];
_HOOK_PRO_FILE()
{
hLogFile = NULL;
memset(szlogfilename, 0, MAX_PATH);
}
}HOOK_PRO_FILE,*PHOOK_PRO_FILE;
class MemLog
{
public:
MemLog();
~MemLog()
{
CloseHandle(MemConfigInfo.hLogFile);
MemConfigInfo.hLogFile = NULL;
}
PHOOK_PRO_FILE GetConfig()
{
return &MemConfigInfo;
}
void init()
{
MemConfigInfo.bViewBlock = GetMemCheckConfigInt("MemPro", "ObserveBlock", 0, MEMINIFILENAME);
MemConfigInfo.bClientHook = GetMemCheckConfigInt("MemPro", "ClientHook", 0, MEMINIFILENAME);
MemConfigInfo.bAllocHook = GetMemCheckConfigInt("MemPro", "bAllocHook", 0, MEMINIFILENAME);
MemConfigInfo.nMemlimit = GetMemCheckConfigInt("MemPro", "Memlimit", 800, MEMINIFILENAME);
}
int GetMemCheckConfigInt(LPCSTR lpszField, LPCSTR lpszKey, int nDefault, LPCSTR lpszmoduleName)
{
char szDirectory[MAX_PATH] = "";
GetCurrentDirectory(MAX_PATH, szDirectory);
char cmodulefigFilePath[MAX_PATH] = "";
sprintf(cmodulefigFilePath, "%s\\MemCheckConfig\\%s", szDirectory, lpszmoduleName);
return GetPrivateProfileInt(lpszField, lpszKey, nDefault, cmodulefigFilePath);
}
DWORD GetMemCheckConfigStr(LPCSTR lpszField, LPCSTR lpszKey, LPSTR lpszValue, DWORD dwMaxLen, LPCSTR lpszDefault, LPCSTR lpszmoduleName)
{
char szDirectory[MAX_PATH] = "";
GetCurrentDirectory(MAX_PATH, szDirectory);
char cmodulefigFilePath[MAX_PATH] = "";
sprintf(cmodulefigFilePath, "%s\\MemCheckConfig\\%s", szDirectory, lpszmoduleName);
return GetPrivateProfileString(lpszField, lpszKey, lpszDefault, lpszValue, dwMaxLen, cmodulefigFilePath);
}
void GetCurrentModule(TCHAR* reallymodname);
HOOK_PRO_FILE MemConfigInfo;
};
class CMemSentry
{
public:
CMemSentry()
{
static MemLog logob;
if (!pMemConfig)
pMemConfig = logob.GetConfig();
_CrtMemCheckpoint(&mBeg);
}
~CMemSentry()
{
_CrtMemCheckpoint(&mEnd);
if (_CrtMemDifference(&mResult, &mBeg, &mEnd))
{
if (pMemConfig&& pMemConfig->bViewBlock)
_CrtMemDumpStatistics(&mResult);
_CrtDumpMemoryLeaks();
}
}
void Watch(const char* szfile,int nline)
{
if (pMemConfig&& pMemConfig->hLogFile)
{
DWORD nWritten;
char szinfo[2][MAX_PATH]{};
strcat(szinfo[0], szfile);
sprintf(szinfo[1], "\n观测行:%d\n", nline);
strcat(szinfo[0], szinfo[1]);
WriteFile(pMemConfig->hLogFile, szinfo, strlen(szinfo[0]), &nWritten, NULL);
_CrtDumpMemoryLeaks();
}
}
static void DumpClientHook(void* userPortion, size_t blockSize)
{
}
static int AllocHook(int nAllocType, void* pvData,size_t nSize, int nBlockUse, long lRequest,
const unsigned char* szFileName, int nLine)
{
if (nAllocType == _HOOK_ALLOC)
{
if (nBlockUse == _CRT_BLOCK)
return TRUE;
static size_t ntotalmem = 0;
ntotalmem += nSize;
if (ntotalmem > 100 * MB)
{
if (pMemConfig && pMemConfig->hLogFile)
{
DWORD nWritten;
char szinfo[2][MAX_PATH]{};
strcat(szinfo[0], (const char*)szFileName);
sprintf(szinfo[1], "\n观测行:%d\n异常内存存量", nLine);
strcat(szinfo[0], szinfo[1]);
WriteFile(pMemConfig->hLogFile, szinfo, strlen(szinfo[0]), &nWritten, NULL);
_CrtDumpMemoryLeaks();
return FALSE;
}
}
}
else
{
}
return TRUE;
}
private:
_CrtMemState mBeg, mEnd, mResult;
static PHOOK_PRO_FILE pMemConfig;
};
inline MemLog::MemLog()
{
if (!MemConfigInfo.hLogFile)
{
TCHAR reallyModuleName[MAX_PATH]{};
GetCurrentModule(reallyModuleName);
strcat(reallyModuleName, ".txt");
init();
if(MemConfigInfo.bClientHook)
_CrtSetDumpClient(CMemSentry::DumpClientHook);
if(MemConfigInfo.bAllocHook)
_CrtSetAllocHook(CMemSentry::AllocHook);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
MemConfigInfo.hLogFile = ::CreateFileA(reallyModuleName, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
_CrtSetReportFile(_CRT_WARN, MemConfigInfo.hLogFile);
}
}
inline void MemLog::GetCurrentModule(TCHAR* reallymodname)
{
ZwQueryInformationThread pZwQueryInformationThread;
HANDLE hThread = GetCurrentThread();
HINSTANCE hNTDLL = ::GetModuleHandle("ntdll");
(FARPROC&)pZwQueryInformationThread = ::GetProcAddress(hNTDLL, "ZwQueryInformationThread");
THREAD_BASIC_INFORMATION tbi;
pZwQueryInformationThread(
hThread,
ThreadBasicInformation,
&tbi,
sizeof(tbi),
NULL
);
TCHAR modname[MAX_PATH]{};
if (GetMappedFileName(OpenProcess(PROCESS_ALL_ACCESS, 0,(DWORD) tbi.ClientId.UniqueProcess), CMemSentry::AllocHook, modname, MAX_PATH) == 0)
{
int res = GetLastError();
exit(0);
}
int nlen = strlen(modname);
int nBeg = 0xFFFFFFFF;
int nEnd = 0xFFFFFFFF;
while (nlen--)
{
if (modname[nlen] == '.')
{
if(nEnd== 0xFFFFFFFF)
nEnd = nlen;
}
if (modname[nlen] == '\\')
{
nBeg = nlen+1;
break;
}
}
for (size_t i = 0; nBeg < nEnd; ++nBeg, ++i)
{
reallymodname[i] = modname[nBeg];
}
}
#include"MemSentry.h"
PHOOK_PRO_FILE CMemSentry::pMemConfig =NULL;