不废话,直接撸代码
#include <stdio.h>
#include <intrin.h>
#pragma intrinsic(_ReturnAddress)
namespace foundation
{
struct FunctionCall
{
std::string FunctionName;
std::string FileName;
int LineNumber;
};
static std::map<const void*, const void*> _memAddrMap;
static std::mutex _memAddrMutex;
void MemleakNewDump2(const void* block, const void* pRetAddr)
{
_memAddrMutex.lock();
_memAddrMap[block] = pRetAddr;
_memAddrMutex.unlock();
}
void memLeakFree2(const void* db)
{
_memAddrMutex.lock();
_memAddrMap.erase(db);
_memAddrMutex.unlock();
}
void dumpMemLeak2()
{
_memAddrMutex.lock();
SYSTEMTIME st;
GetLocalTime(&st);
char sz[MAX_PATH + 4];
sprintf(sz, "memLeak-%d-%02d-%02d=%02d-%02d-%02d.txt", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
FILE* f = fopen(sz, "w");
if (!f)
{
_memAddrMutex.unlock();
return;
}
int cnt = 0;
char _sz[256];
// Walk through the stack frames.
HANDLE hProcess = GetCurrentProcess();
HANDLE hThread = GetCurrentThread();
if (!SymInitialize(hProcess, NULL, TRUE))
{
SymCleanup(hProcess);
_memAddrMutex.unlock();
fclose(f);
return;
}
// 1. Get function name at the address
const int nBuffSize = (sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64);
ULONG64 symbolBuffer[nBuffSize];
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = MAX_SYM_NAME;
for (auto it : _memAddrMap)
{
FunctionCall curCall;
curCall.FunctionName = "";
curCall.FileName = "";
curCall.LineNumber = 0;
DWORD64 dwSymDisplacement = 0;
if (SymFromAddr(hProcess, (DWORD64)(it.second), &dwSymDisplacement, pSymbol))
{
curCall.FunctionName = pSymbol->Name;
}
//2. get line and file name at the address
IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE64) };
DWORD dwLineDisplacement = 0;
if (SymGetLineFromAddr64(hProcess, (DWORD64)(it.second), &dwLineDisplacement, &lineInfo))
{
curCall.FileName = (lineInfo.FileName);
curCall.LineNumber = lineInfo.LineNumber;
}
cnt++;
fprintf(f, "\n%d\n", cnt);
fprintf(f, "FileName: %s\n", curCall.FileName.c_str());
fprintf(f, "FunctionName: %s\n", curCall.FunctionName.c_str());
fprintf(f, "LineNumber: %d\n", curCall.LineNumber);
fprintf(f, "======================================\n\n");
}
SymCleanup(hProcess);
fclose(f);
_memAddrMutex.unlock();
}
};
int main(int argc, char* argv[])
{
int ret = 0;
int* p = new int;
foundation::dumpMemLeak2();//<--
return ret;
}
#define GUI_MEMLEAK_DETECT
void* __cdecl operator new(size_t const size)
{
for (;;)
{
if (void* const block = malloc(size))
{
#ifdef GUI_MEMLEAK_DETECT
const void* p = _ReturnAddress();
foundation::MemleakNewDump2(block, p);//<--
#endif
return block;
}
if (_callnewh(size) == 0)
{
if (size == SIZE_MAX)
{
throw std::exception("bad alloc, SIZE_MAX");
}
else
{
throw std::exception("bad alloc");
}
}
}
}
void __cdecl operator delete(void* p)
{
#if !defined(_ATL_NO_DEBUG_CRT) && defined(_DEBUG)
_free_dbg(p, _NORMAL_BLOCK);
#else
free(p);
#endif
#ifdef GUI_MEMLEAK_DETECT
foundation::memLeakFree2(p); //<--
#endif
}