RCFProto
 All Classes Functions Typedefs
MemLeakDetect.h
1 
2 // JL: This code originated from a CodeProject article:
3 // http://www.codeproject.com/KB/cpp/MemLeakDetect.aspx
4 
5 #pragma once
6 
7 #include "CallStack.hpp"
8 
9 // CRT memory tracking only works in debug builds.
10 // Note also that stack traces are only available on x86 builds.
11 #if defined(_DEBUG)
12 
13 #define _CRTDBG_MAP_ALLOC
14 #include <map>
15 #define _CRTBLD
16 #include <windows.h>
17 
18 #include <..\crt\src\dbgint.h>
19 #include <dbghelp.h>
20 #include <crtdbg.h>
21 
22 #include <boost/filesystem/path.hpp>
23 
24 class CMemLeakDetect
25 {
26  public:
27 
28  struct AllocBlockInfo : public CallStack
29  {
30  AllocBlockInfo() : address(NULL), size(0), lineNumber(0), occurance(0)
31  {
32  memset(fileName, 0, MLD_MAX_NAME_LENGTH * sizeof(TCHAR));
33  }
34 
35  void* address;
36  DWORD size;
37  TCHAR fileName[MLD_MAX_NAME_LENGTH];
38  DWORD lineNumber;
39  DWORD occurance;
40  };
41 
42  typedef std::map<LPVOID, AllocBlockInfo> KEYMAP;
43  typedef std::map<LPVOID, AllocBlockInfo>::iterator POSITION;
44  typedef std::pair<LPVOID, AllocBlockInfo> KEYVALUE;
45 
46  class CMapMem
47  {
48  public:
49 
50  KEYMAP m_Map;
51  POSITION m_Pos;
52 
53  inline BOOL Lookup(LPVOID pAddr, AllocBlockInfo& aInfo) {
54 
55  m_Pos = m_Map.find(pAddr);
56  //
57  if (m_Pos == m_Map.end())
58  {
59  return FALSE;
60  }
61  //
62  pAddr = m_Pos->first;
63  aInfo = m_Pos->second;
64 
65  return TRUE;
66  };
67 
68  inline POSITION end() {
69 
70  return m_Map.end();
71  };
72 
73  inline void RemoveKey(LPVOID pAddr) {
74 
75  m_Map.erase(pAddr);
76  };
77 
78  inline void RemoveAll() {
79  m_Map.clear();
80  };
81 
82  void SetAt(LPVOID pAddr, AllocBlockInfo& aInfo) {
83 
84  m_Map[pAddr] = aInfo;
85  };
86 
87  inline POSITION GetStartPosition() {
88  POSITION pos = m_Map.begin();
89  return pos;
90  };
91 
92  inline void GetNextAssoc(POSITION& pos, LPVOID& rAddr, AllocBlockInfo& aInfo) {
93 
94  rAddr = pos->first;
95  aInfo = pos->second;
96  pos++;
97  };
98 
99  void InitHashTable(int preAllocEntries, BOOL flag) {
100  preAllocEntries = NULL;
101  flag = NULL;
102  };
103 
104  };
105 
106  CMemLeakDetect(const TCHAR * outputDir = NULL);
107  ~CMemLeakDetect();
108  void Init();
109  void End();
110  void addMemoryTrace(void* addr, DWORD asize, TCHAR *fname, DWORD lnum);
111  void redoMemoryTrace(void* addr, void* oldaddr, DWORD asize, TCHAR *fname, DWORD lnum);
112  void removeMemoryTrace(void* addr, void* realdataptr);
113  void cleanupMemoryTrace();
114  void writeOutput(const TCHAR * szOutput);
115  void dumpMemoryTrace();
116  //
117 
118  CMapMem m_AllocatedMemoryList;
119  DWORD memoccurance;
120  bool isLocked;
121  //
122  private:
123 
124  public:
125  std::vector<std::basic_string<TCHAR> > m_funcsToIgnore;
126  boost::filesystem::path m_outputFolder;
127 
128 
129  private:
130  std::string m_outputPath;
131  std::ofstream m_output;
132 };
133 
134 #else
135 
136 // Dummy replacement for release.
137 class CMemLeakDetect
138 {
139 public:
140  CMemLeakDetect(const TCHAR * = NULL)
141  {
142  }
143 };
144 
145 #endif
146 
147 // JL: Example instrumentation usage - in a loop that causes memory growth,
148 // get stack traces of outstanding allocations after each iteration. Stack
149 // traces get written to a sequence of text files.
150 
151 //std::auto_ptr<CMemLeakDetect> leakDetectorPtr;
152 //while (true)
153 //{
154 // leakDetectPtr.reset( new CMemLeakDetect() );
155 //
156 // // Leaky code here
157 // // ...
158 //
159 // // A new text file will be produced for each iteration.
160 // leakDetectPtr.reset();
161 //}