手写Visual C++软件内存泄漏检测代码

13 篇文章 0 订阅

不废话,直接撸代码

#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
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值