本篇blog附带的所有工具和代码下载地址如下:
http://download.csdn.net/detail/zengraoli/5348827
文中的memcheck晚点的时候在把它打包成dll
不多数都是用的Dbgview.exe,话说还不错,我一直想找的仅仅是一个检测内存泄露的class,没想到csdn上面问,找到了这么一个工具,参看csdn论坛链接http://bbs.csdn.net/topics/390452307
#include <iostream> #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中出现了下面的信息:
Detected memory leaks
这个是提示
但在这上面显然有不太好的地方,比如我需要知道哪一行导致的内存泄露,所以参考csdn blog的一篇文章:http://blog.csdn.net/iuhsihsow/article/details/8492363
#include "stdafx.h" #include <iostream> #include "string" #include "vector" using namespace std; #ifdef _DEBUG #define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> #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中出现了下面的信息:
可以看到正是25行的地方导致内存泄露的
参考文章:http://www.cnblogs.com/FCoding/archive/2012/07/04/2576877.html
Code没来得及细看,能用就是了^_^,方便就行,枉自猜测一下原理----------重载了new和delete,对他俩进行一个计数,并记下行数,两个不为偶数,则就是代表已经出现内存泄露了
#ifndef MEMCHECK_H #define MEMCHECK_H #include <cstddef> // 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
#include <cstdio> #include <cstdlib> #include <cassert> 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 <iostream> #include <vector> #include <cstring> #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<MyClass*> myClasses; myClasses.push_back(new MyClass()); myClasses.push_back(new MyClass()); std::vector<void*> 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<int> v; v.push_back(1); Foo s("goodbye"); } int main() { TRACE_OFF(); MEM_ON(); Test(); Test2(); Test3(); MEM_OFF(); }
在我编译的时候,会出现一下提示:
运行的时候出现:
1、使用时在工程中加入在MemCheck.h,而且这个.h文件应该放在所以头文件的后边,因为里面有这么一句代码:#undef new
2、用MEM_ON()和MEM_OFF()来打开和关闭检测
3、TRACE_ON()和TRACE_OFF()用来打开或关闭检测结果的输出(上面的测试代码中使用没做检测结果的输出)
4、可以检测代码中使用了流、标准容器,以及某个类的构造函数分配了空间