c++内存泄露检测,长文慎入!

关于内存泄露的,今天无意想到,网上找了一下


本篇blog附带的所有工具和代码下载地址如下:

http://download.csdn.net/detail/zengraoli/5348827


文中的memcheck晚点的时候在把它打包成dll


一、使用Dbgview.exe

不多数都是用的Dbgview.exe,话说还不错,我一直想找的仅仅是一个检测内存泄露的class,没想到csdn上面问,找到了这么一个工具,参看csdn论坛链接http://bbs.csdn.net/topics/390452307

来个测试工程:

#include 
#include "string"
#include "vector"
using namespace std;

int main()
{
	{
		char *str;
		str = new char[100 + 1];

		strcpy(str, "zengraoli");

		cout << str << endl;
	}

	_CrtDumpMemoryLeaks();   // 内存泄露检测

	return 0;
}

Ctrl+F5后,在Dbgview.exe中出现了下面的信息:

c++内存泄露检测,长文慎入!_第1张图片


Detected memory leaks

这个是提示

上面的测试不方便的地方:

但在这上面显然有不太好的地方,比如我需要知道哪一行导致的内存泄露,所以参考csdn blog的一篇文章:http://blog.csdn.net/iuhsihsow/article/details/8492363

再次修改:

#include "stdafx.h"
#include 
#include "string"
#include "vector"
using namespace std;

#ifdef	_DEBUG
#define _CRTDBG_MAP_ALLOC
#include 
#include 
#define newEx   new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif

inline void EnableMemLeakCheck()
{
	_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
}

int _tmain(int argc, _TCHAR* argv[])
{
	EnableMemLeakCheck();

	char *str = newEx char[9 + 1];

	cout << str << endl;

	return 0;
}



Ctrl+F5后,在Dbgview.exe中出现了下面的信息:

c++内存泄露检测,长文慎入!_第2张图片


可以看到正是25行的地方导致内存泄露的

二、不使用Dbgview.exe,直接使用class

参考文章:http://www.cnblogs.com/FCoding/archive/2012/07/04/2576877.html

Code没来得及细看,能用就是了^_^,方便就行,枉自猜测一下原理----------重载了newdelete,对他俩进行一个计数,并记下行数,两个不为偶数,则就是代表已经出现内存泄露了

MemCheck.h

#ifndef MEMCHECK_H
#define MEMCHECK_H
#include   // for size_t

// Hijack the new operator (both scalar and array versions)
void* operator new(std::size_t, const char*, long);
void* operator new[](std::size_t, const char*, long);
#define new new (__FILE__, __LINE__)

extern bool traceFlag;
#define TRACE_ON() traceFlag = true
#define TRACE_OFF() traceFlag = false

extern bool activeFlag;
#define MEM_ON() activeFlag = true
#define MEM_OFF() activeFlag = false

#endif

MemCheck.cpp

#include 
#include 
#include 
using namespace std;
#undef new

// Global flags set by macros in MemCheck.h
bool traceFlag  = true;
bool activeFlag = false;

namespace 
{
	// Memory map entry type
	struct Info 
	{
		void* ptr;
		const char* file;
		long  line;
	};

	// Memory map data
	const  size_t MAXPTRS = 10000u;
	Info   memMap[MAXPTRS];
	size_t nptrs = 0;

	// Searches the map for an address
	int findPtr(void* p) 
	{
		for (int i = 0; i < nptrs; ++i)
		{
			if (memMap[i].ptr == p)
			{
				return i;
			}
		}
		return -1;
	}

	void delPtr(void* p)
	{
		int pos = findPtr(p);
		assert(p >= 0);
		// Remove pointer from map
		for (size_t i = pos; i < nptrs-1; ++i)
		{
			memMap[i] = memMap[i+1];
		}
		--nptrs;
	}

	// Dummy type for static destructor
	struct Sentinel 
	{
		~Sentinel()
		{
			if (nptrs > 0) 
			{
				printf("Leaked memory at:\n");
				for (size_t i = 0; i < nptrs; ++i)
				{
					printf("\t%p (file: %s, line %ld)\n", 
							memMap[i].ptr, memMap[i].file, memMap[i].line);
				}
			}
			else
			{
				printf("No user memory leaks!\n");
			}				
		}
	};

	// Static dummy object
	Sentinel s;

} // End anonymous namespace

// Overload scalar new
void* operator new(size_t siz, const char* file,
				   long line) 
{
	void* p = malloc(siz);
	if (activeFlag)
	{
		if (nptrs == MAXPTRS)
		{
			printf("memory map too small (increase MAXPTRS)\n");
			exit(1);
		}
		memMap[nptrs].ptr = p;
		memMap[nptrs].file = file;
		memMap[nptrs].line = line;
		++nptrs;
	}
	if (traceFlag) 
	{
		printf("Allocated %u bytes at address %p ", siz, p);
		printf("(file: %s, line: %ld)\n", file, line);
	}
	return p;
}

// Overload array new
void* operator new[](size_t siz, const char* file,
					 long line)
{
	return operator new(siz, file, line);
}

// Override scalar delete
void operator delete(void* p) 
{
	if (findPtr(p) >= 0) 
	{
		free(p);
		assert(nptrs > 0);
		delPtr(p);
		if (traceFlag)
		{
			printf("Deleted memory at address %p\n", p);
		}
	}
	else if (!p && activeFlag)
	{
		printf("Attempt to delete unknown pointer: %p\n", p);
	}	
}

// Override array delete
void operator delete[](void* p)
{
	operator delete(p);
}

那哥们的测试工程,挺不错的,有3种情况:

#include "stdafx.h"
#include 
#include 
#include 

#include "MemCheck.h"   // Must appear last!
using namespace std;

void Test()
{
	int *i = new int(0);
}

class MyClass
{
private:
	int *p;
public:
	MyClass()
	{
		if(p != NULL)
		{
			p = new int(0);
		}
	}
	~MyClass()
	{
		if(p != NULL)
		{
			delete p;
			p = NULL;
		}
	}
};

void Test2()
{
	int *i = NULL; 	// better for read
	i = new int(0);    
	int *&y = i; 	// pointer's reference
	delete i;

	MyClass *pMyClass = new MyClass();

	std::vector myClasses;
	myClasses.push_back(new MyClass());
	myClasses.push_back(new MyClass());

	std::vector myVector;
	myVector.push_back(new MyClass());
	myVector.push_back(new MyClass());
	delete (MyClass *)(myVector.at(0));
	delete myVector.at(1); // memory leak
}

class Foo 
{
	char* s;
public:
	Foo(const char*s ) 
	{
		this->s = new char[strlen(s) + 1];
		strcpy(this->s, s);
	}
	~Foo() 
	{
		delete [] s;
	}
};

void Test3()
{
	cout << "hello\n";
	int* p = new int;
	delete p;
	int* q = new int[3];
	delete [] q;
	/**//*delete r;*/
	vector v;
	v.push_back(1);
	Foo s("goodbye");
}

int main() 
{
	TRACE_OFF();
	MEM_ON();
	Test();
	Test2();
	Test3();
	MEM_OFF();
}

在我编译的时候,会出现一下提示:



运行的时候出现:

c++内存泄露检测,长文慎入!_第3张图片


对这个cpp的使用说明:

1、使用时在工程中加入在MemCheck.h,而且这个.h文件应该放在所以头文件的后边,因为里面有这么一句代码:#undef new

2、用MEM_ON()MEM_OFF()来打开和关闭检测

3TRACE_ON()TRACE_OFF()用来打开或关闭检测结果的输出(上面的测试代码中使用没做检测结果的输出)

4、可以检测代码中使用了流、标准容器,以及某个类的构造函数分配了空间


你可能感兴趣的:(C,C++)