Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

400 lines
7.5 KiB

  1. /*
  2. * @doc INTERNAL
  3. *
  4. * @module utilmem.cpp - Debug memory tracking/allocation routines
  5. *
  6. * History: <nl>
  7. * 8/17/99 KeithCu Move to a separate module to prevent errors.
  8. *
  9. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
  10. */
  11. #define W32SYS_CPP
  12. #include "_common.h"
  13. #undef PvAlloc
  14. #undef PvReAlloc
  15. #undef FreePv
  16. #undef new
  17. #if defined(DEBUG)
  18. #undef PvSet
  19. #undef ZeroMemory
  20. #undef strcmp
  21. MST vrgmst[100];
  22. typedef struct tagPVH //PV Header
  23. {
  24. char *szFile;
  25. int line;
  26. tagPVH *ppvhNext;
  27. int cbAlloc; //On Win'95, the size returned is not the size allocated.
  28. int magicPvh; //Should be last
  29. } PVH;
  30. #define cbPvh (sizeof(PVH))
  31. typedef struct //PV Tail
  32. {
  33. int magicPvt; //Must be first
  34. } PVT;
  35. #define cbPvt (sizeof(PVT))
  36. #define cbPvDebug (cbPvh + cbPvt)
  37. void *vpHead = 0;
  38. /*
  39. * UpdateMst(void)
  40. *
  41. * @func Fills up the vrgmst structure with summary information about our memory
  42. * usage.
  43. *
  44. * @rdesc
  45. * void
  46. */
  47. void UpdateMst(void)
  48. {
  49. W32->ZeroMemory(vrgmst, sizeof(vrgmst));
  50. PVH *ppvh;
  51. MST *pmst;
  52. ppvh = (PVH*) vpHead;
  53. while (ppvh != 0)
  54. {
  55. pmst = vrgmst;
  56. //Look for entry in list...
  57. while (pmst->szFile)
  58. {
  59. if (W32->strcmp(pmst->szFile, ppvh->szFile) == 0)
  60. {
  61. pmst->cbAlloc += ppvh->cbAlloc;
  62. break;
  63. }
  64. pmst++;
  65. }
  66. if (pmst->szFile == 0)
  67. {
  68. pmst->szFile = ppvh->szFile;
  69. pmst->cbAlloc = ppvh->cbAlloc;
  70. }
  71. ppvh = ppvh->ppvhNext;
  72. }
  73. }
  74. /*
  75. * PvDebugValidate(void)
  76. *
  77. * @func Verifies the the node is proper. Pass in a pointer to the users data
  78. * (after the header node.)
  79. *
  80. * @rdesc
  81. * void
  82. */
  83. void PvDebugValidate(void *pv)
  84. {
  85. PVH *ppvh;
  86. UNALIGNED PVT *ppvt;
  87. ppvh = (PVH*) ((char*) pv - cbPvh);
  88. ppvt = (PVT*) ((char*) pv + ppvh->cbAlloc);
  89. AssertSz(ppvh->magicPvh == 0x12345678, "PvDebugValidate: header bytes are corrupt");
  90. AssertSz(ppvt->magicPvt == 0xfedcba98, "PvDebugValidate: tail bytes are corrupt");
  91. }
  92. /*
  93. * CW32System::PvSet(pv, szFile, line)
  94. *
  95. * @mfunc Sets a different module and line number for
  96. *
  97. * @rdesc
  98. * void
  99. */
  100. void CW32System::PvSet(void *pv, char *szFile, int line)
  101. {
  102. if (pv == 0)
  103. return;
  104. PvDebugValidate(pv);
  105. PVH *ppvh = (PVH*) ((char*) pv - cbPvh);
  106. ppvh->szFile = szFile;
  107. ppvh->line = line;
  108. }
  109. /*
  110. * CW32System::PvAllocDebug(cb, uiMemFlags, szFile, line)
  111. *
  112. * @mfunc Allocates a generic (void*) pointer. This is a debug only routine which
  113. * tracks the allocation.
  114. *
  115. * @rdesc
  116. * void
  117. */
  118. void* CW32System::PvAllocDebug(ULONG cb, UINT uiMemFlags, char *szFile, int line)
  119. {
  120. void *pv;
  121. pv = PvAlloc(cb + cbPvDebug, uiMemFlags);
  122. if (!pv)
  123. return 0;
  124. PVH *ppvh;
  125. UNALIGNED PVT *ppvt;
  126. ppvt = (PVT*) ((char*) pv + cb + cbPvh);
  127. ppvh = (PVH*) pv;
  128. ZeroMemory(ppvh, sizeof(PVH));
  129. ppvh->magicPvh = 0x12345678;
  130. ppvt->magicPvt = 0xfedcba98;
  131. ppvh->szFile = szFile;
  132. ppvh->line = line;
  133. ppvh->cbAlloc = cb;
  134. ppvh->ppvhNext = (PVH*) vpHead;
  135. vpHead = pv;
  136. return (char*) pv + cbPvh;
  137. }
  138. /*
  139. * CW32System::PvReAllocDebug(pv, cb, szFile, line)
  140. *
  141. * @mfunc ReAllocates a generic (void*) pointer. This is a debug only routine which
  142. * tracks the allocation.
  143. *
  144. * @rdesc
  145. * void
  146. */
  147. void* CW32System::PvReAllocDebug(void *pv, ULONG cb, char *szFile, int line)
  148. {
  149. void *pvNew;
  150. PVH *ppvh, *ppvhHead, *ppvhTail;
  151. UNALIGNED PVT *ppvt;
  152. ppvh = (PVH*) ((char*) pv - cbPvh);
  153. if (!pv)
  154. return PvAllocDebug(cb, 0, szFile, line);
  155. PvDebugValidate(pv);
  156. pvNew = PvReAlloc((char*) pv - cbPvh, cb + cbPvDebug);
  157. if (!pvNew)
  158. return 0;
  159. ppvt = (PVT*) ((char*) pvNew + cb + cbPvh);
  160. ppvh = (PVH*) pvNew;
  161. ppvh->cbAlloc = cb;
  162. //Put the new trailer bytes in.
  163. ppvt->magicPvt = 0xfedcba98;
  164. //Make the pointer list up to date again
  165. if (pv != pvNew)
  166. {
  167. ppvhTail = 0;
  168. ppvhHead = (PVH*) vpHead;
  169. while ((char*)ppvhHead != (char*)pv - cbPvh)
  170. {
  171. AssertSz(ppvhHead, "entry not found in list.");
  172. ppvhTail = ppvhHead;
  173. ppvhHead = (PVH*) ppvhHead->ppvhNext;
  174. }
  175. if (ppvhTail == 0)
  176. vpHead = pvNew;
  177. else
  178. ppvhTail->ppvhNext = (PVH*) pvNew;
  179. }
  180. return (char*) pvNew + cbPvh;
  181. }
  182. /*
  183. * CW32System::FreePvDebug(pv)
  184. *
  185. * @mfunc Returns a pointer when you are done with it.
  186. *
  187. * @rdesc
  188. * void
  189. */
  190. void CW32System::FreePvDebug(void *pv)
  191. {
  192. if (!pv)
  193. return;
  194. PvDebugValidate(pv);
  195. PVH *ppvhHead, *ppvhTail, *ppvh;
  196. AssertSz(vpHead, "Deleting from empty free list.");
  197. ppvh = (PVH*) ((char*) pv - cbPvh);
  198. //Search and remove the entry from the list
  199. ppvhTail = 0;
  200. ppvhHead = (PVH*) vpHead;
  201. while ((char*) ppvhHead != ((char*) pv - cbPvh))
  202. {
  203. AssertSz(ppvhHead, "entry not found in list.");
  204. ppvhTail = ppvhHead;
  205. ppvhHead = (PVH*) ppvhHead->ppvhNext;
  206. }
  207. if (ppvhTail == 0)
  208. vpHead = ppvhHead->ppvhNext;
  209. else
  210. ppvhTail->ppvhNext = ppvhHead->ppvhNext;
  211. FreePv((char*) pv - cbPvh);
  212. }
  213. /*
  214. * CatchLeaks(void)
  215. *
  216. * @func Displays any memory leaks in a dialog box.
  217. *
  218. * @rdesc
  219. * void
  220. */
  221. void CatchLeaks(void)
  222. {
  223. PVH *ppvh;
  224. char szLeak[512];
  225. ppvh = (PVH*) vpHead;
  226. while (ppvh != 0)
  227. {
  228. #ifndef NOFULLDEBUG
  229. wsprintfA(szLeak, "Memory Leak of %d bytes: -- File: %s, Line: %d", ppvh->cbAlloc, ppvh->szFile, ppvh->line);
  230. #endif
  231. if (NULL != pfnAssert)
  232. {
  233. // if we have an assert hook, give the user a chance to process the leak message
  234. if (pfnAssert(szLeak, ppvh->szFile, &ppvh->line))
  235. {
  236. #ifdef NOFULLDEBUG
  237. DebugBreak();
  238. #else
  239. // hook returned true, show the message box
  240. MessageBoxA(NULL, szLeak, "", MB_OK);
  241. #endif
  242. }
  243. }
  244. else
  245. {
  246. #ifdef NOFULLDEBUG
  247. DebugBreak();
  248. #else
  249. MessageBoxA(NULL, szLeak, "", MB_OK);
  250. #endif
  251. }
  252. ppvh = ppvh->ppvhNext;
  253. }
  254. }
  255. void* _cdecl operator new (size_t size, char *szFile, int line)
  256. {
  257. TRACEBEGIN(TRCSUBSYSEDIT, TRCSCOPEINTERN, "new");
  258. return W32->PvAllocDebug(size, GMEM_ZEROINIT, szFile, line);
  259. }
  260. void _cdecl operator delete (void* pv)
  261. {
  262. TRACEBEGIN(TRCSUBSYSEDIT, TRCSCOPEINTERN, "delete");
  263. W32->FreePvDebug(pv);
  264. }
  265. #else //DEBUG
  266. void* _cdecl operator new (size_t size)
  267. {
  268. TRACEBEGIN(TRCSUBSYSEDIT, TRCSCOPEINTERN, "new");
  269. return W32->PvAlloc(size, GMEM_ZEROINIT);
  270. }
  271. void _cdecl operator delete (void* pv)
  272. {
  273. TRACEBEGIN(TRCSUBSYSEDIT, TRCSCOPEINTERN, "delete");
  274. W32->FreePv(pv);
  275. }
  276. #endif //DEBUG
  277. HANDLE g_hHeap;
  278. /*
  279. * PvAlloc (cbBuf, uiMemFlags)
  280. *
  281. * @mfunc memory allocation. Similar to GlobalAlloc.
  282. *
  283. * @comm The only flag of interest is GMEM_ZEROINIT, which
  284. * specifies that memory should be zeroed after allocation.
  285. */
  286. PVOID CW32System::PvAlloc(
  287. ULONG cbBuf, //@parm Count of bytes to allocate
  288. UINT uiMemFlags) //@parm Flags controlling allocation
  289. {
  290. TRACEBEGIN(TRCSUBSYSEDIT, TRCSCOPEINTERN, "PvAlloc");
  291. if (g_hHeap == 0)
  292. {
  293. CLock lock;
  294. g_hHeap = HeapCreate(0, 0, 0);
  295. }
  296. void *pv = HeapAlloc(g_hHeap, (uiMemFlags & GMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0, cbBuf);
  297. return pv;
  298. }
  299. /*
  300. * PvReAlloc (pv, cbBuf)
  301. *
  302. * @mfunc memory reallocation.
  303. *
  304. */
  305. PVOID CW32System::PvReAlloc(
  306. PVOID pv, //@parm Buffer to reallocate
  307. DWORD cbBuf) //@parm New size of buffer
  308. {
  309. TRACEBEGIN(TRCSUBSYSEDIT, TRCSCOPEINTERN, "PvReAlloc");
  310. if(pv)
  311. return HeapReAlloc(g_hHeap, 0, pv, cbBuf);
  312. return PvAlloc(cbBuf, 0);
  313. }
  314. /*
  315. * FreePv (pv)
  316. *
  317. * @mfunc frees memory
  318. *
  319. * @rdesc void
  320. */
  321. void CW32System::FreePv(
  322. PVOID pv) //@parm Buffer to free
  323. {
  324. TRACEBEGIN(TRCSUBSYSEDIT, TRCSCOPEINTERN, "FreePv");
  325. if(pv)
  326. HeapFree(g_hHeap, 0, pv);
  327. }