Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
MemDebug.cpp
Go to the documentation of this file.
1 /* Project nGen
2  John DiCamillo
3  Copyright © 1997-2001. All Rights Reserved.
4 
5  SUBSYSTEM: foundation
6  FILE: MemDebug.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Memory Debugging class
13 */
14 
15 #include "MemDebug.h"
16 
17 #include <stdio.h>
18 #include <string.h>
19 #include <crtdbg.h>
20 #include <malloc.h>
21 
22 // +--------------------------------------------------------------------+
23 
24 static Memory::LEVEL mem_chk_level = Memory::PERIODIC;
25 
26 #ifdef _DEBUG
27 static _CrtMemState mem_chk_p1,
28  mem_chk_p2;
29 #endif
30 
31 static HANDLE mem_log_file = 0;
32 
33 // +--------------------------------------------------------------------+
34 
35 #ifdef _DEBUG
36 #define CrtSetDebugField(a) _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
37 #define CrtClrDebugField(a) _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
38 #endif
39 
40 static void heapdump()
41 {
42  _HEAPINFO hinfo;
43  int heapstatus;
44  DWORD used = 0;
45  DWORD avail = 0;
46  char report[256];
47 
48  hinfo._pentry = NULL;
49  while ((heapstatus = _heapwalk( &hinfo )) == _HEAPOK) {
50  sprintf_s(report, "%6s block at %Fp of size %4.4X\n",
51  ( hinfo._useflag == _USEDENTRY ? "USED" : "FREE" ),
52  hinfo._pentry, hinfo._size);
53 
54  _RPT0(_CRT_WARN, report);
55 
56  if (hinfo._useflag == _USEDENTRY)
57  used += hinfo._size;
58  else
59  avail += hinfo._size;
60  }
61 
62  sprintf_s(report, "------\nUsed Blocks: %d\nAvail Blocks: %d\nTotal Blocks: %d\n", used, avail, used+avail);
63  _RPT0(_CRT_WARN, report);
64 
65  switch (heapstatus) {
66  case _HEAPEMPTY:
67  _RPT0(_CRT_WARN, "OK - empty heap\n" );
68  break;
69  case _HEAPEND:
70  _RPT0(_CRT_WARN, "OK - end of heap\n" );
71  break;
72  case _HEAPBADPTR:
73  _RPT0(_CRT_WARN, "ERROR - bad pointer to heap\n" );
74  break;
75  case _HEAPBADBEGIN:
76  _RPT0(_CRT_WARN, "ERROR - bad start of heap\n" );
77  break;
78  case _HEAPBADNODE:
79  _RPT0(_CRT_WARN, "ERROR - bad node in heap\n" );
80  break;
81  }
82 }
83 
84 // +--------------------------------------------------------------------+
85 
86 void
87 Memory::OpenLog(const char* filename)
88 {
89 #ifdef _DEBUG
90  if (!filename || !strlen(filename))
91  filename = "memdbg.txt";
92 
93  mem_log_file = CreateFile(filename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
94 
95  if (mem_log_file) {
96  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
97  _CrtSetReportFile(_CRT_WARN, mem_log_file);
98  _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
99  _CrtSetReportFile(_CRT_ERROR, mem_log_file);
100  _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
101  _CrtSetReportFile(_CRT_ASSERT, mem_log_file);
102  }
103 
104  _CrtMemCheckpoint(&mem_chk_p1);
105 #endif
106 }
107 
108 // +--------------------------------------------------------------------+
109 
110 void
112 {
113 #ifdef _DEBUG
114  if (mem_log_file) {
115  CloseHandle(mem_log_file);
116  mem_log_file = 0;
117 
118  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
119  _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
120  _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
121  _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
122  _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
123  _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
124  }
125 #endif
126 }
127 
128 // +--------------------------------------------------------------------+
129 
130 void
132 {
133 #ifdef _DEBUG
134  if (! _CrtCheckMemory()) {
135  _RPT0(_CRT_ERROR, "\n\nMemory Check Failed.\n");
136  heapdump();
137  Checkpoint();
138  _asm { int 3 }
139  exit(1111);
140  }
141 #endif
142 }
143 
144 // +--------------------------------------------------------------------+
145 
146 void
148 {
149 #ifdef _DEBUG
150  if (mem_chk_level < PERIODIC) return;
151 
152  _RPT0(_CRT_WARN, "\n\nMemory Checkpoint:\n"
153  "--------------------------------------------------\n");
154 
155  _CrtMemState s;
156  _CrtMemCheckpoint(&mem_chk_p2);
157  _CrtMemDifference(&s, &mem_chk_p1, &mem_chk_p2);
158  _CrtMemDumpStatistics(&s);
159 
160  memcpy(&mem_chk_p1, &mem_chk_p2, sizeof(mem_chk_p1));
161 #endif
162 }
163 
164 // +--------------------------------------------------------------------+
165 
166 void
168 {
169 #ifdef _DEBUG
170  if (mem_chk_level < PERIODIC) return;
171 
172  _RPT0(_CRT_WARN, "\n\nMemory Stats:\n"
173  "--------------------------------------------------\n");
174 
175  _CrtMemState s;
176  _CrtMemCheckpoint(&s);
177  _CrtMemDumpStatistics(&s);
178 #endif
179 }
180 
181 // +--------------------------------------------------------------------+
182 
183 void
185 {
186 #ifdef _DEBUG
187  _RPT0(_CRT_WARN, "\n\nMemory Dump Leaks:\n"
188  "--------------------------------------------------\n");
189  _CrtDumpMemoryLeaks();
190 #endif
191 }
192 
193 // +--------------------------------------------------------------------+
194 
195 void
197 {
198 #ifdef _DEBUG
199  mem_chk_level = l;
200 
201  _CrtSetDbgFlag(0);
202 
203  switch (mem_chk_level) {
204  case MAXIMAL: CrtSetDebugField(_CRTDBG_CHECK_ALWAYS_DF);
205  case PERIODIC: CrtSetDebugField(_CRTDBG_DELAY_FREE_MEM_DF);
206  case LEAKS: CrtSetDebugField(_CRTDBG_LEAK_CHECK_DF);
207  case OFF:
208  default: break;
209  }
210 #endif
211 }
212