Source code of Windows XP (NT5)
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.

981 lines
22 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. basemem.c
  5. Abstract:
  6. Implements macros and declares functions for basic allocation functions.
  7. Consolidated into this file from debug.c and main.c
  8. Author:
  9. Marc R. Whitten (marcw) 09-Sep-1999
  10. Revision History:
  11. --*/
  12. #include "pch.h"
  13. //
  14. // Includes
  15. //
  16. #include "utilsp.h"
  17. //
  18. // Constants
  19. //
  20. #ifdef DEBUG
  21. #define TRAIL_SIG 0x708aa210
  22. #define TRACK_SIGNATURE 0x30405060
  23. #endif
  24. //
  25. // Macros
  26. //
  27. #define REUSE_SIZE_PTR(ptr) ((PDWORD) ((PBYTE) ptr - sizeof (DWORD)))
  28. #define REUSE_TAG_PTR(ptr) ((PDWORD) ((PBYTE) ptr + (*REUSE_SIZE_PTR(ptr))))
  29. //
  30. // Types
  31. //
  32. #ifdef DEBUG
  33. typedef struct _tagTRACKSTRUCT {
  34. DWORD Signature;
  35. PCSTR File;
  36. DWORD Line;
  37. SIZE_T Size;
  38. PSTR Comment;
  39. PCSTR CallerFile;
  40. DWORD CallerLine;
  41. BOOL Allocated;
  42. struct _tagTRACKSTRUCT *PrevAlloc;
  43. struct _tagTRACKSTRUCT *NextAlloc;
  44. } TRACKSTRUCT, *PTRACKSTRUCT;
  45. #endif
  46. //
  47. // Globals
  48. //
  49. #ifdef DEBUG
  50. PTRACKSTRUCT g_TrackHead = NULL;
  51. #endif
  52. //
  53. // Heap debug statistics
  54. //
  55. static SIZE_T g_TotalBytesAllocated = 0;
  56. static SIZE_T g_MaxBytesInUse = 0;
  57. static SIZE_T g_HeapAllocs = 0;
  58. static SIZE_T g_HeapReAllocs = 0;
  59. static SIZE_T g_HeapFrees = 0;
  60. static SIZE_T g_HeapAllocFails = 0;
  61. static SIZE_T g_HeapReAllocFails = 0;
  62. static SIZE_T g_HeapFreeFails = 0;
  63. //
  64. // Out of memory string -- loaded at initialization
  65. //
  66. PCSTR g_OutOfMemoryString = NULL;
  67. PCSTR g_OutOfMemoryRetry = NULL;
  68. HWND g_OutOfMemoryParentWnd;
  69. //
  70. // Macro expansion list
  71. //
  72. // None
  73. //
  74. // Private function prototypes
  75. //
  76. #ifdef DEBUG
  77. SIZE_T
  78. pDebugHeapValidatePtrUnlocked (
  79. HANDLE hHeap,
  80. PCVOID CallerPtr,
  81. PCSTR File,
  82. DWORD Line
  83. );
  84. VOID
  85. pTrackInsert (
  86. PCSTR File,
  87. DWORD Line,
  88. SIZE_T Size,
  89. PTRACKSTRUCT p
  90. );
  91. VOID
  92. pTrackDelete (
  93. PTRACKSTRUCT p
  94. );
  95. #endif
  96. //
  97. // Macro expansion definition
  98. //
  99. // None
  100. //
  101. // Code
  102. //
  103. void
  104. HeapCallFailed (
  105. PCSTR Msg,
  106. PCSTR File,
  107. DWORD Line
  108. )
  109. {
  110. CHAR Msg2[2048];
  111. wsprintfA (Msg2, "Error in %s line %u\n\n", File, Line);
  112. if (_tcslen(Msg) + _tcslen(Msg2) < 2025) {
  113. strcat (Msg2, Msg);
  114. }
  115. strcat (Msg2, "\n\nBreak execution now?");
  116. if (IDYES == MessageBoxA (GetFocus(), Msg2, "Heap Call Failed", MB_YESNO|MB_APPLMODAL)) {
  117. DebugBreak ();
  118. }
  119. }
  120. #ifdef DEBUG
  121. SIZE_T
  122. DebugHeapValidatePtr (
  123. HANDLE hHeap,
  124. PCVOID CallerPtr,
  125. PCSTR File,
  126. DWORD Line
  127. )
  128. {
  129. SIZE_T rc;
  130. EnterCriticalSection (&g_MemAllocCs);
  131. rc = pDebugHeapValidatePtrUnlocked (hHeap, CallerPtr, File, Line);
  132. LeaveCriticalSection (&g_MemAllocCs);
  133. return rc;
  134. }
  135. SIZE_T
  136. pDebugHeapValidatePtrUnlocked (
  137. HANDLE hHeap,
  138. PCVOID CallerPtr,
  139. PCSTR File,
  140. DWORD Line
  141. )
  142. {
  143. SIZE_T size;
  144. PCVOID RealPtr;
  145. SIZE_T SizeAdjust;
  146. SizeAdjust = sizeof (TRACKSTRUCT);
  147. RealPtr = (PCVOID) ((PBYTE) CallerPtr - SizeAdjust);
  148. if (IsBadWritePtr ((PBYTE) RealPtr - 8, 8)) {
  149. CHAR BadPtrMsg[256];
  150. //lint --e(572)
  151. wsprintfA (
  152. BadPtrMsg,
  153. "Attempt to free memory at 0x%08x%08x. This address is not valid.",
  154. (DWORD)((UBINT)CallerPtr >> 32),
  155. (DWORD)(UBINT)CallerPtr
  156. );
  157. HeapCallFailed (BadPtrMsg, File, Line);
  158. return (SIZE_T)INVALID_PTR;
  159. }
  160. size = HeapSize (hHeap, 0, RealPtr);
  161. if (size == (SIZE_T)-1) {
  162. CHAR BadPtrMsg[256];
  163. //lint --e(572)
  164. wsprintfA (
  165. BadPtrMsg,
  166. "Attempt to free memory at 0x%08x%08x. "
  167. "This address is not the start of a memory block.",
  168. (DWORD)((UBINT)CallerPtr >> 32),
  169. (DWORD)(UBINT)CallerPtr
  170. );
  171. HeapCallFailed (BadPtrMsg, File, Line);
  172. return (SIZE_T)INVALID_PTR;
  173. }
  174. return size;
  175. }
  176. PVOID
  177. DebugHeapAlloc (
  178. PCSTR File,
  179. DWORD Line,
  180. HANDLE hHeap,
  181. DWORD Flags,
  182. SIZE_T BytesToAlloc
  183. )
  184. {
  185. PVOID RealPtr;
  186. PVOID ReturnPtr = NULL;
  187. DWORD SizeAdjust;
  188. DWORD TrackStructSize;
  189. DWORD OrgError;
  190. EnterCriticalSection (&g_MemAllocCs);
  191. __try {
  192. OrgError = GetLastError();
  193. SizeAdjust = sizeof (TRACKSTRUCT) + sizeof (DWORD);
  194. TrackStructSize = sizeof (TRACKSTRUCT);
  195. if (!HeapValidate (hHeap, 0, NULL)) {
  196. HeapCallFailed ("Heap is corrupt!", File, Line);
  197. // we want to go on, most likely we will AV shortly
  198. }
  199. RealPtr = SafeHeapAlloc(hHeap, Flags, BytesToAlloc + SizeAdjust);
  200. if (RealPtr) {
  201. g_HeapAllocs++;
  202. g_TotalBytesAllocated += HeapSize (hHeap, 0, RealPtr);
  203. g_MaxBytesInUse = max (g_MaxBytesInUse, g_TotalBytesAllocated);
  204. pTrackInsert (File, Line, BytesToAlloc, (PTRACKSTRUCT) RealPtr);
  205. *((PDWORD) ((PBYTE) RealPtr + TrackStructSize + BytesToAlloc)) = TRAIL_SIG;
  206. }
  207. else {
  208. g_HeapAllocFails++;
  209. }
  210. if (RealPtr) {
  211. ReturnPtr = (PVOID) ((PBYTE) RealPtr + TrackStructSize);
  212. }
  213. if (ReturnPtr && !(Flags & HEAP_ZERO_MEMORY)) {
  214. FillMemory (ReturnPtr, BytesToAlloc, 0xAA);
  215. }
  216. if (RealPtr) {
  217. SetLastError(OrgError);
  218. }
  219. }
  220. __finally {
  221. LeaveCriticalSection (&g_MemAllocCs);
  222. }
  223. return ReturnPtr;
  224. }
  225. PVOID
  226. DebugHeapReAlloc (
  227. PCSTR File,
  228. DWORD Line,
  229. HANDLE hHeap,
  230. DWORD Flags,
  231. PCVOID CallerPtr,
  232. SIZE_T BytesToAlloc
  233. )
  234. {
  235. UBINT lastSize;
  236. PVOID NewRealPtr;
  237. PCVOID RealPtr;
  238. PVOID ReturnPtr = NULL;
  239. DWORD SizeAdjust;
  240. DWORD OrgError;
  241. DWORD TrackStructSize;
  242. SIZE_T OrgSize;
  243. PTRACKSTRUCT pts = NULL;
  244. EnterCriticalSection (&g_MemAllocCs);
  245. __try {
  246. OrgError = GetLastError();
  247. SizeAdjust = sizeof (TRACKSTRUCT) + sizeof (DWORD);
  248. TrackStructSize = sizeof (TRACKSTRUCT);
  249. RealPtr = (PCVOID) ((PBYTE) CallerPtr - TrackStructSize);
  250. pts = (PTRACKSTRUCT) RealPtr;
  251. OrgSize = pts->Size;
  252. if (!HeapValidate (hHeap, 0, NULL)) {
  253. HeapCallFailed ("Heap is corrupt!", File, Line);
  254. // we want to go on, most likely we will AV shortly
  255. }
  256. lastSize = pDebugHeapValidatePtrUnlocked (hHeap, CallerPtr, File, Line);
  257. if (lastSize == (UBINT)INVALID_PTR) {
  258. // we want to go on, most likely we will AV shortly
  259. }
  260. pTrackDelete (pts);
  261. NewRealPtr = SafeHeapReAlloc (hHeap, Flags, (PVOID) RealPtr, BytesToAlloc + SizeAdjust);
  262. if (NewRealPtr) {
  263. g_HeapReAllocs++;
  264. g_TotalBytesAllocated -= lastSize;
  265. g_TotalBytesAllocated += HeapSize (hHeap, 0, NewRealPtr);
  266. g_MaxBytesInUse = max (g_MaxBytesInUse, g_TotalBytesAllocated);
  267. pTrackInsert (File, Line, BytesToAlloc, (PTRACKSTRUCT) NewRealPtr);
  268. *((PDWORD) ((PBYTE) NewRealPtr + TrackStructSize + BytesToAlloc)) = TRAIL_SIG;
  269. }
  270. else {
  271. g_HeapReAllocFails++;
  272. // Put original address back in
  273. pTrackInsert (
  274. pts->File,
  275. pts->Line,
  276. pts->Size,
  277. pts
  278. );
  279. }
  280. if (NewRealPtr) {
  281. ReturnPtr = (PVOID) ((PBYTE) NewRealPtr + TrackStructSize);
  282. }
  283. if (ReturnPtr && BytesToAlloc > OrgSize && !(Flags & HEAP_ZERO_MEMORY)) {
  284. FillMemory ((PBYTE) ReturnPtr + OrgSize, BytesToAlloc - OrgSize, 0xAA);
  285. }
  286. if (ReturnPtr) {
  287. SetLastError (OrgError);
  288. }
  289. }
  290. __finally {
  291. LeaveCriticalSection (&g_MemAllocCs);
  292. }
  293. return ReturnPtr;
  294. }
  295. BOOL
  296. DebugHeapFree (
  297. PCSTR File,
  298. DWORD Line,
  299. HANDLE hHeap,
  300. DWORD Flags,
  301. PCVOID CallerPtr
  302. )
  303. {
  304. UBINT size;
  305. PCVOID RealPtr;
  306. DWORD SizeAdjust;
  307. DWORD OrgError;
  308. BOOL Result = FALSE;
  309. PTRACKSTRUCT pts = NULL;
  310. EnterCriticalSection (&g_MemAllocCs);
  311. __try {
  312. OrgError = GetLastError();
  313. SizeAdjust = sizeof (TRACKSTRUCT);
  314. RealPtr = (PCVOID) ((PBYTE) CallerPtr - SizeAdjust);
  315. pts = (PTRACKSTRUCT) RealPtr;
  316. if (*((PDWORD) ((PBYTE) CallerPtr + pts->Size)) != TRAIL_SIG) {
  317. HeapCallFailed ("Heap tag was overwritten!", File, Line);
  318. __leave;
  319. }
  320. if (!HeapValidate (hHeap, 0, NULL)) {
  321. HeapCallFailed ("Heap is corrupt!", File, Line);
  322. g_HeapFreeFails++;
  323. __leave;
  324. }
  325. size = pDebugHeapValidatePtrUnlocked (hHeap, CallerPtr, File, Line);
  326. if (size == (UBINT)INVALID_PTR) {
  327. g_HeapFreeFails++;
  328. __leave;
  329. }
  330. pTrackDelete ((PTRACKSTRUCT) RealPtr);
  331. if (!HeapFree (hHeap, Flags, (PVOID) RealPtr)) {
  332. CHAR BadPtrMsg[256];
  333. wsprintfA (
  334. BadPtrMsg,
  335. "Attempt to free memory at 0x%08x with flags 0x%08x. "
  336. "HeapFree() failed.",
  337. CallerPtr,
  338. Flags
  339. );
  340. HeapCallFailed (BadPtrMsg, File, Line);
  341. g_HeapFreeFails++;
  342. __leave;
  343. }
  344. g_HeapFrees++;
  345. if (g_TotalBytesAllocated < size) {
  346. DEBUGMSG ((DBG_WARNING, "Total bytes allocated is less than amount being freed. "
  347. "This suggests memory corruption."));
  348. g_TotalBytesAllocated = 0;
  349. } else {
  350. g_TotalBytesAllocated -= size;
  351. }
  352. SetLastError (OrgError);
  353. Result = TRUE;
  354. }
  355. __finally {
  356. LeaveCriticalSection (&g_MemAllocCs);
  357. }
  358. return Result;
  359. }
  360. VOID
  361. DumpHeapStats (
  362. VOID
  363. )
  364. {
  365. CHAR OutputMsg[4096];
  366. wsprintfA (OutputMsg,
  367. "Bytes currently allocated: %u\n"
  368. "Peak bytes allocated: %u\n"
  369. "Allocation count: %u\n"
  370. "Reallocation count: %u\n"
  371. "Free count: %u\n",
  372. g_TotalBytesAllocated,
  373. g_MaxBytesInUse,
  374. g_HeapAllocs,
  375. g_HeapReAllocs,
  376. g_HeapFrees
  377. );
  378. if (g_HeapAllocFails) {
  379. wsprintfA (strchr (OutputMsg, 0),
  380. "***Allocation failures: %u\n",
  381. g_HeapAllocFails);
  382. }
  383. if (g_HeapReAllocFails) {
  384. wsprintfA (strchr (OutputMsg, 0),
  385. "***Reallocation failures: %u\n",
  386. g_HeapReAllocFails);
  387. }
  388. if (g_HeapFreeFails) {
  389. wsprintfA (strchr (OutputMsg, 0),
  390. "***Free failures: %u\n",
  391. g_HeapFreeFails);
  392. }
  393. DEBUGMSG ((DBG_STATS, "%s", OutputMsg));
  394. #ifdef CONSOLE
  395. printf ("%s", OutputMsg);
  396. #endif // #ifndef CONSOLE
  397. }
  398. void
  399. DebugHeapCheck (
  400. PCSTR File,
  401. DWORD Line,
  402. HANDLE hHeap
  403. )
  404. {
  405. EnterCriticalSection (&g_MemAllocCs);
  406. if (!HeapValidate (hHeap, 0, NULL)) {
  407. HeapCallFailed ("HeapCheck failed: Heap is corrupt!", File, Line);
  408. }
  409. LeaveCriticalSection (&g_MemAllocCs);
  410. }
  411. #endif
  412. PVOID
  413. ReuseAlloc (
  414. HANDLE Heap,
  415. PVOID OldPtr,
  416. DWORD SizeNeeded
  417. )
  418. {
  419. DWORD CurrentSize;
  420. PVOID Ptr = NULL;
  421. UINT AllocAdjustment = sizeof(DWORD);
  422. //
  423. // HeapSize is not very good, so while it may look good, don't
  424. // use it.
  425. //
  426. #ifdef DEBUG
  427. AllocAdjustment += sizeof (DWORD);
  428. #endif
  429. if (!OldPtr) {
  430. Ptr = MemAlloc (Heap, 0, SizeNeeded + AllocAdjustment);
  431. } else {
  432. CurrentSize = *REUSE_SIZE_PTR(OldPtr);
  433. #ifdef DEBUG
  434. if (*REUSE_TAG_PTR(OldPtr) != 0x10a28a70) {
  435. DEBUGMSG ((DBG_WHOOPS, "MemReuse detected corruption!"));
  436. Ptr = MemAlloc (Heap, 0, SizeNeeded + AllocAdjustment);
  437. } else
  438. #endif
  439. if (SizeNeeded > CurrentSize) {
  440. SizeNeeded += 1024 - (SizeNeeded & 1023);
  441. Ptr = MemReAlloc (Heap, 0, REUSE_SIZE_PTR(OldPtr), SizeNeeded + AllocAdjustment);
  442. OldPtr = NULL;
  443. }
  444. }
  445. if (Ptr) {
  446. *((PDWORD) Ptr) = SizeNeeded;
  447. Ptr = (PVOID) ((PBYTE) Ptr + sizeof (DWORD));
  448. #ifdef DEBUG
  449. *REUSE_TAG_PTR(Ptr) = 0x10a28a70;
  450. #endif
  451. }
  452. return Ptr ? Ptr : OldPtr;
  453. }
  454. VOID
  455. ReuseFree (
  456. HANDLE Heap,
  457. PVOID Ptr
  458. )
  459. {
  460. if (Ptr) {
  461. MemFree (Heap, 0, REUSE_SIZE_PTR(Ptr));
  462. }
  463. }
  464. VOID
  465. SetOutOfMemoryParent (
  466. HWND hwnd
  467. )
  468. {
  469. g_OutOfMemoryParentWnd = hwnd;
  470. }
  471. VOID
  472. OutOfMemory_Terminate (
  473. VOID
  474. )
  475. {
  476. if (!g_OutOfMemoryString || !g_OutOfMemoryString[0]) {
  477. return;
  478. }
  479. MessageBoxA (
  480. g_OutOfMemoryParentWnd,
  481. g_OutOfMemoryString,
  482. NULL,
  483. MB_OK|MB_ICONHAND|MB_SYSTEMMODAL|MB_SETFOREGROUND|MB_TOPMOST
  484. );
  485. ExitProcess (0);
  486. //
  487. // Not needed, will never get here
  488. //
  489. // TerminateProcess (GetModuleHandle (NULL), 0);
  490. }
  491. VOID
  492. pValidateBlock (
  493. PVOID Block,
  494. SIZE_T Size
  495. )
  496. /*++
  497. Routine Description:
  498. pValidateBlock makes sure Block is non-NULL. If it is NULL, then the user
  499. is given a popup, unless the request size is bogus.
  500. There are two cases for the popup.
  501. - If g_OutOfMemoryParentWnd was set with SetOutOfMemoryParent,
  502. then the user is asked to close other programs, and is given a retry
  503. option.
  504. - If there is no out of memory parent, then the user is told they
  505. need to get more memory.
  506. In either case, Setup is terminated. In GUI mode, Setup will be
  507. stuck and the machine will be unbootable.
  508. Arguments:
  509. Block - Specifies the block to validate.
  510. Size - Specifies the request size
  511. Return Value:
  512. none
  513. --*/
  514. {
  515. LONG rc;
  516. if (!Block && Size < 0x2000000) {
  517. if (g_OutOfMemoryParentWnd) {
  518. rc = MessageBoxA (
  519. g_OutOfMemoryParentWnd,
  520. g_OutOfMemoryRetry,
  521. NULL,
  522. MB_RETRYCANCEL|MB_ICONHAND|MB_SYSTEMMODAL|MB_SETFOREGROUND|MB_TOPMOST
  523. );
  524. if (rc == IDCANCEL) {
  525. OutOfMemory_Terminate();
  526. }
  527. } else {
  528. OutOfMemory_Terminate();
  529. }
  530. } else {
  531. if (!Block) {
  532. // this is serious. We want to break now and give Dr. Watson a
  533. // chance to get our stack.
  534. DebugBreak ();
  535. }
  536. }
  537. }
  538. PVOID
  539. SafeHeapAlloc (
  540. HANDLE Heap,
  541. DWORD Flags,
  542. SIZE_T Size
  543. )
  544. {
  545. PVOID Block;
  546. do {
  547. Block = HeapAlloc (Heap, Flags, Size);
  548. pValidateBlock (Block, Size);
  549. } while (!Block);
  550. return Block;
  551. }
  552. PVOID
  553. SafeHeapReAlloc (
  554. HANDLE Heap,
  555. DWORD Flags,
  556. PVOID OldBlock,
  557. SIZE_T Size
  558. )
  559. {
  560. PVOID Block;
  561. do {
  562. Block = HeapReAlloc (Heap, Flags, OldBlock, Size);
  563. pValidateBlock (Block, Size);
  564. } while (!Block);
  565. return Block;
  566. }
  567. #ifdef DEBUG
  568. VOID
  569. pTrackInsert (
  570. PCSTR File,
  571. DWORD Line,
  572. SIZE_T Size,
  573. PTRACKSTRUCT p
  574. )
  575. {
  576. p->Signature = TRACK_SIGNATURE;
  577. if (g_TrackAlloc) {
  578. p->File = SafeHeapAlloc (g_hHeap, 0, SizeOfStringA (File));
  579. if (p->File) {
  580. StringCopyA ((PSTR)p->File, File);
  581. }
  582. } else {
  583. p->File = File;
  584. p->Allocated = FALSE;
  585. }
  586. p->Line = Line;
  587. p->Size = Size;
  588. p->Comment = g_TrackComment ? SafeHeapAlloc (g_hHeap, 0, SizeOfStringA (g_TrackComment)) : NULL;
  589. p->PrevAlloc = NULL;
  590. p->NextAlloc = g_TrackHead;
  591. p->CallerFile = g_TrackFile;
  592. p->CallerLine = g_TrackLine;
  593. if (p->Comment) {
  594. StringCopyA (p->Comment, g_TrackComment);
  595. }
  596. if (g_TrackHead) {
  597. g_TrackHead->PrevAlloc = p;
  598. }
  599. g_TrackHead = p;
  600. }
  601. VOID
  602. pTrackDelete (
  603. PTRACKSTRUCT p
  604. )
  605. {
  606. if (p->Signature != TRACK_SIGNATURE) {
  607. DEBUGMSG ((DBG_WARNING, "A tracking signature is invalid. "
  608. "This suggests memory corruption."));
  609. return;
  610. }
  611. if (p->PrevAlloc) {
  612. p->PrevAlloc->NextAlloc = p->NextAlloc;
  613. } else {
  614. g_TrackHead = p->NextAlloc;
  615. }
  616. if (p->NextAlloc) {
  617. p->NextAlloc->PrevAlloc = p->PrevAlloc;
  618. }
  619. if (p->Allocated) {
  620. if (p->File) {
  621. HeapFree (g_hHeap, 0, (PSTR)p->File);
  622. }
  623. }
  624. }
  625. VOID
  626. DumpHeapLeaks (
  627. VOID
  628. )
  629. {
  630. CHAR LineBuf[4096];
  631. PTRACKSTRUCT p;
  632. BOOL BadMem = FALSE;
  633. if (g_TrackHead) {
  634. __try {
  635. for (p = g_TrackHead ; p ; p = p->NextAlloc) {
  636. __try {
  637. if (p->Comment) {
  638. if (p->CallerFile) {
  639. wsprintfA (
  640. LineBuf,
  641. "%s line %u\n"
  642. " %s\n"
  643. " Caller: %s line %u",
  644. p->File,
  645. p->Line,
  646. p->Comment,
  647. p->CallerFile,
  648. p->CallerLine
  649. );
  650. } else {
  651. wsprintfA (LineBuf, "%s line %u\n %s", p->File, p->Line, p->Comment);
  652. }
  653. } else {
  654. if (p->CallerFile) {
  655. wsprintfA (
  656. LineBuf,
  657. "%s line %u\n"
  658. " Caller: %s line %u\n",
  659. p->File,
  660. p->Line,
  661. p->CallerFile,
  662. p->CallerLine
  663. );
  664. } else {
  665. wsprintfA (LineBuf, "(direct alloc) %s line %u", p->File, p->Line);
  666. }
  667. }
  668. }
  669. __except (TRUE) {
  670. wsprintfA (LineBuf, "Address %Xh was freed, but not by MemFree!!", p);
  671. BadMem = TRUE;
  672. }
  673. DEBUGMSG (("Leaks", "%s", LineBuf));
  674. #ifdef CONSOLE
  675. printf ("%s", LineBuf);
  676. #endif
  677. //lint --e(774)
  678. if (BadMem) {
  679. break;
  680. }
  681. }
  682. }
  683. __except (TRUE) {
  684. }
  685. }
  686. }
  687. /*
  688. VOID
  689. DumpHeapLeaks (
  690. VOID
  691. )
  692. {
  693. HANDLE File;
  694. CHAR LineBuf[2048];
  695. PTRACKSTRUCT p;
  696. DWORD DontCare;
  697. DWORD Count;
  698. BOOL BadMem = FALSE;
  699. CHAR TempPath[MAX_TCHAR_PATH];
  700. CHAR memtrackLogPath[] = "?:\\memtrack.log";
  701. GetSystemDirectory(TempPath, MAX_TCHAR_PATH);
  702. memtrackLogPath[0] = TempPath[0];
  703. File = CreateFileA (memtrackLogPath, GENERIC_WRITE, 0, NULL,
  704. OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
  705. );
  706. if (File != INVALID_HANDLE_VALUE) {
  707. SetFilePointer (File, 0, NULL, FILE_END);
  708. if (g_TrackHead) {
  709. Count = 0;
  710. __try {
  711. for (p = g_TrackHead ; p ; p = p->NextAlloc) {
  712. Count++;
  713. __try {
  714. if (p->Comment) {
  715. if (p->CallerFile) {
  716. wsprintfA (
  717. LineBuf,
  718. "%s line %u\r\n"
  719. " %s\r\n"
  720. " Caller: %s line %u\r\n"
  721. "\r\n",
  722. p->File,
  723. p->Line,
  724. p->Comment,
  725. p->CallerFile,
  726. p->CallerLine
  727. );
  728. } else {
  729. wsprintfA (LineBuf, "%s line %u\r\n %s\r\n\r\n", p->File, p->Line, p->Comment);
  730. }
  731. } else {
  732. if (p->CallerFile) {
  733. wsprintfA (
  734. LineBuf,
  735. "%s line %u\r\n"
  736. " Caller: %s line %u\r\n"
  737. "\r\n",
  738. p->File,
  739. p->Line,
  740. p->CallerFile,
  741. p->CallerLine
  742. );
  743. } else {
  744. wsprintfA (LineBuf, "(direct alloc) %s line %u\r\n\r\n", p->File, p->Line);
  745. }
  746. }
  747. }
  748. __except (TRUE) {
  749. wsprintfA (LineBuf, "Address %Xh was freed, but not by MemFree!!\r\n", p);
  750. BadMem = TRUE;
  751. }
  752. WriteFile (File, LineBuf, (DWORD)ByteCountA (LineBuf), &DontCare, NULL);
  753. //lint --e(774)
  754. if (BadMem) {
  755. break;
  756. }
  757. }
  758. }
  759. __except (TRUE) {
  760. }
  761. wsprintfA (LineBuf, "\r\n%i item%s allocated but not freed.\r\n\r\n", Count, Count == 1 ? "":"s");
  762. WriteFile (File, LineBuf, (DWORD)ByteCountA (LineBuf), &DontCare, NULL);
  763. }
  764. wsprintfA (
  765. LineBuf,
  766. "Bytes currently allocated: %u\r\n"
  767. "Peak bytes allocated: %u\r\n"
  768. "Allocation count: %u\r\n"
  769. "Reallocation count: %u\r\n"
  770. "Free count: %u\r\n\r\n\r\n\r\n\r\n",
  771. g_TotalBytesAllocated,
  772. g_MaxBytesInUse,
  773. g_HeapAllocs,
  774. g_HeapReAllocs,
  775. g_HeapFrees
  776. );
  777. WriteFile (File, LineBuf, (DWORD)ByteCountA (LineBuf), &DontCare, NULL);
  778. CloseHandle (File);
  779. }
  780. }
  781. */
  782. #endif