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.

930 lines
21 KiB

  1. #include "hostenv.h"
  2. #include "cmallspy.h"
  3. #include "apglobal.h"
  4. #define cbAlign 32
  5. #define HEADERSIZE cbAlign // # of bytes of block header
  6. #define TRAILERSIZE cbAlign // # of bytes of block trailer
  7. static XCHAR g_rgchHead[] = XSTR("OLEAuto Mem Head"); // beginning of block signature
  8. static XCHAR g_rgchTail[] = XSTR("OLEAuto Mem Tail"); // end of block signature
  9. #define MEMCMP(PV1, PV2, CB) memcmp((PV1), (PV2), (CB))
  10. #define MEMCPY(PV1, PV2, CB) memcpy((PV1), (PV2), (CB))
  11. #define MEMSET(PV, VAL, CB) memset((PV), (VAL), (CB))
  12. #define MALLOC(CB) GlobalLock(GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, CB))
  13. CMallocSpy myMallocSpy;
  14. UINT g_cHeapCheckInterval = 10; // only check full heap every 100 times.
  15. //---------------------------------------------------------------------
  16. // implementation of the debug allocator
  17. //---------------------------------------------------------------------
  18. CAddrNode32 FAR* CAddrNode32::m_pnFreeList = NULL;
  19. // AddrNodes are allocated in blocks to reduce the number of allocations
  20. // we do for these. Note, we get away with this because the addr nodes
  21. // are never freed, so we can just allocate a block, and thread them
  22. // onto the freelist.
  23. //
  24. #define MEM_cAddrNodes 128
  25. void FAR* CAddrNode32::operator new(size_t /*cb*/)
  26. {
  27. CAddrNode32 FAR* pn;
  28. if(m_pnFreeList == NULL)
  29. {
  30. pn = (CAddrNode32 FAR*)MALLOC(sizeof(CAddrNode32) * MEM_cAddrNodes);
  31. for(int i = 1; i < MEM_cAddrNodes-1; ++i)
  32. pn[i].m_pnNext = &pn[i+1];
  33. pn[MEM_cAddrNodes-1].m_pnNext = m_pnFreeList;
  34. m_pnFreeList = &pn[1];
  35. }
  36. else
  37. {
  38. pn = m_pnFreeList;
  39. m_pnFreeList = pn->m_pnNext;
  40. }
  41. return pn;
  42. }
  43. void CAddrNode32::operator delete(void FAR* pv)
  44. {
  45. CAddrNode32 FAR *pn;
  46. pn = (CAddrNode32 FAR*)pv;
  47. pn->m_pnNext = m_pnFreeList;
  48. m_pnFreeList = pn;
  49. }
  50. //+---------------------------------------------------------------------
  51. //
  52. // Member: CMallocSpy::CMallocSpy
  53. //
  54. // Synopsis: Constructor
  55. //
  56. // Returns:
  57. //
  58. // History: 24-Oct-94 Created.
  59. //
  60. // Notes:
  61. //
  62. //----------------------------------------------------------------------
  63. CMallocSpy::CMallocSpy(void)
  64. {
  65. m_cRef = 0;
  66. m_fWantTrueSize = FALSE;
  67. m_cAllocCalls = 0;
  68. m_cHeapChecks = 0;
  69. MEMSET(m_rganode, 0, sizeof(m_rganode));
  70. }
  71. //+---------------------------------------------------------------------
  72. //
  73. // Member: CMallocSpy::~CMallocSpy
  74. //
  75. // Synopsis: Destructor
  76. //
  77. // Returns:
  78. //
  79. // History: 24-Oct-94 Created.
  80. //
  81. // Notes:
  82. //
  83. //----------------------------------------------------------------------
  84. CMallocSpy::~CMallocSpy(void)
  85. {
  86. CheckForLeaks();
  87. }
  88. //+---------------------------------------------------------------------
  89. //
  90. // Member: CMallocSpy::QueryInterface
  91. //
  92. // Synopsis: Only IUnknown and IMallocSpy are meaningful
  93. //
  94. // Arguments: [riid] --
  95. // [ppUnk] --
  96. //
  97. // Returns: S_OK or E_NOINTERFACE
  98. //
  99. // History: 24-Oct-94 Created.
  100. //
  101. // Notes:
  102. //
  103. //----------------------------------------------------------------------
  104. HRESULT CMallocSpy::QueryInterface(REFIID riid, LPVOID *ppUnk)
  105. {
  106. HRESULT hr = S_OK;
  107. if (IsEqualIID(riid, IID_IUnknown))
  108. {
  109. *ppUnk = (IUnknown *) this;
  110. }
  111. else if (IsEqualIID(riid, IID_IMallocSpy))
  112. {
  113. *ppUnk = (IMalloc *) this;
  114. }
  115. else
  116. {
  117. *ppUnk = NULL;
  118. return E_NOINTERFACE;
  119. }
  120. AddRef();
  121. return hr;
  122. }
  123. //+---------------------------------------------------------------------
  124. //
  125. // Member: CMallocSpy::AddRef
  126. //
  127. // Synopsis: Add a reference
  128. //
  129. // Returns: New reference count
  130. //
  131. // History: 24-Oct-94 Created.
  132. //
  133. // Notes:
  134. //
  135. //----------------------------------------------------------------------
  136. ULONG CMallocSpy::AddRef(void)
  137. {
  138. return ++m_cRef;
  139. }
  140. //+---------------------------------------------------------------------
  141. //
  142. // Member: CMallocSpy::Release
  143. //
  144. // Synopsis: Remove a reference
  145. //
  146. // Returns: The new reference count
  147. //
  148. // History: 24-Oct-94 Created.
  149. //
  150. // Notes:
  151. //
  152. //----------------------------------------------------------------------
  153. ULONG CMallocSpy::Release(void)
  154. {
  155. ULONG cRef;
  156. cRef = --m_cRef;
  157. if (cRef == 0)
  158. {
  159. #if 0 // don't delete -- we're statically allocated
  160. delete this;
  161. #endif
  162. }
  163. return cRef;
  164. }
  165. //+---------------------------------------------------------------------
  166. //
  167. // Member: CMallocSpy::PreAlloc
  168. //
  169. // Synopsis: Called prior to OLE calling IMalloc::Alloc
  170. //
  171. // Arguments: [cbRequest] -- The number of bytes the caller of
  172. // is requesting IMalloc::Alloc
  173. //
  174. // Returns: The count of bytes to actually allocate
  175. //
  176. // History: 24-Oct-94 Created.
  177. //
  178. // Notes:
  179. //
  180. //----------------------------------------------------------------------
  181. SIZE_T CMallocSpy::PreAlloc(SIZE_T cbRequest)
  182. {
  183. HeapCheck();
  184. return cbRequest + HEADERSIZE + TRAILERSIZE;
  185. }
  186. //+---------------------------------------------------------------------
  187. //
  188. // Member: CMallocSpy::PostAlloc
  189. //
  190. // Synopsis: Called after OLE calls IMalloc::Alloc
  191. //
  192. // Arguments: [pActual] -- The allocation returned by IMalloc::Alloc
  193. //
  194. // Returns: The allocation pointer to return to the caller of
  195. // IMalloc::Alloc
  196. //
  197. // History: 24-Oct-94 Created.
  198. //
  199. // Notes:
  200. //
  201. //----------------------------------------------------------------------
  202. void *CMallocSpy::PostAlloc(void *pActual)
  203. {
  204. IMalloc *pmalloc;
  205. SIZE_T cbRequest;
  206. HRESULT hresult;
  207. XCHAR sz[20];
  208. if (pActual == NULL) // if real alloc failed, then
  209. return NULL; // propogate failure
  210. if (FAILED(hresult = CoGetMalloc(MEMCTX_TASK, &pmalloc)))
  211. {
  212. apSPrintf(sz, XSTR("%lX"), hresult);
  213. apLogFailInfo(XSTR("ERROR:CoGetMalloc failed!!!"), XSTR("NOEEROR"), sz, XSTR(""));
  214. return(NULL);
  215. }
  216. m_fWantTrueSize = TRUE;
  217. cbRequest = pmalloc->GetSize(pActual) - HEADERSIZE - TRAILERSIZE;
  218. m_fWantTrueSize = FALSE;
  219. pmalloc->Release();
  220. // set header signature
  221. MEMCPY(pActual, g_rgchHead, HEADERSIZE);
  222. // set trailer signature
  223. MEMCPY((BYTE *)pActual+HEADERSIZE+cbRequest, g_rgchTail, TRAILERSIZE);
  224. // save info for leak detection
  225. AddInst((BYTE *)pActual+HEADERSIZE, cbRequest);
  226. // Return the allocation plus offset
  227. return (void *) (((BYTE *) pActual) + HEADERSIZE);
  228. }
  229. //+---------------------------------------------------------------------
  230. //
  231. // Member: CMallocSpy::PreFree
  232. //
  233. // Synopsis: Called prior to OLE calling IMalloc::Free
  234. //
  235. // Arguments: [pRequest] -- The allocation to be freed
  236. // [fSpyed] -- Whether it was allocated with a spy active
  237. //
  238. // Returns:
  239. //
  240. // History: 24-Oct-94 Created.
  241. //
  242. // Notes:
  243. //
  244. //----------------------------------------------------------------------
  245. void *CMallocSpy::PreFree(void *pRequest, BOOL fSpyed)
  246. {
  247. HeapCheck();
  248. if (pRequest == NULL)
  249. {
  250. return NULL;
  251. }
  252. // Undo the offset
  253. if (fSpyed)
  254. {
  255. CAddrNode32 FAR* pn;
  256. SIZE_T sizeToFree;
  257. pn = FindInst(pRequest);
  258. // check for attempt to operate on a pointer we didn't allocate
  259. if(pn == NULL)
  260. {
  261. apLogFailInfo(XSTR("Attempt to free memory not allocated by this 32-bit test!"), XSTR(""), XSTR(""), XSTR(""));
  262. }
  263. // check the block we're freeing
  264. VerifyHeaderTrailer(pn);
  265. sizeToFree = pn->m_cb + HEADERSIZE + TRAILERSIZE;
  266. DelInst(pRequest);
  267. // mark entire block as invalid
  268. MEMSET((BYTE *) pRequest - HEADERSIZE, '~', sizeToFree);
  269. return (void *) (((BYTE *) pRequest) - HEADERSIZE);
  270. }
  271. else
  272. {
  273. return pRequest;
  274. }
  275. }
  276. //+---------------------------------------------------------------------
  277. //
  278. // Member: CMallocSpy::PostFree
  279. //
  280. // Synopsis: Called after OLE calls IMalloc::Free
  281. //
  282. // Arguments: [fSpyed] -- Whether it was allocated with a spy active
  283. //
  284. // Returns:
  285. //
  286. // History: 24-Oct-94 Created.
  287. //
  288. // Notes:
  289. //
  290. //----------------------------------------------------------------------
  291. void CMallocSpy::PostFree(BOOL /*fSpyed*/)
  292. {
  293. return;
  294. }
  295. //+---------------------------------------------------------------------
  296. //
  297. // Member: CMallocSpy::PreRealloc
  298. //
  299. // Synopsis: Called prior to OLE calling IMalloc::Realloc
  300. //
  301. // Arguments: [pRequest] -- The buffer to be reallocated
  302. // [cbRequest] -- The requested new size of the buffer
  303. // [ppNewRequest] -- Where to store the new buffer pointer
  304. // to be reallocated
  305. // [fSpyed] -- Whether it was allocated with a spy active
  306. //
  307. // Returns: The new size to actually be allocated
  308. //
  309. // History: 24-Oct-94 Created.
  310. //
  311. // Notes:
  312. //
  313. //----------------------------------------------------------------------
  314. SIZE_T CMallocSpy::PreRealloc(void *pRequest, SIZE_T cbRequest, void **ppNewRequest, BOOL fSpyed)
  315. {
  316. HeapCheck();
  317. if (fSpyed)
  318. {
  319. CAddrNode32 FAR* pn;
  320. SIZE_T sizeToFree;
  321. pn = FindInst(pRequest);
  322. // check for attempt to operate on a pointer we didn't allocate
  323. if(pn == NULL)
  324. {
  325. apLogFailInfo(XSTR("Attempt to reallocate memory not allocated by this 32-bit test!"), XSTR(""), XSTR(""), XSTR(""));
  326. }
  327. sizeToFree = pn->m_cb;
  328. *ppNewRequest = (void *) (((BYTE *) pRequest) - HEADERSIZE);
  329. m_pvRealloc = pRequest;
  330. return cbRequest + HEADERSIZE + TRAILERSIZE;
  331. }
  332. else
  333. {
  334. *ppNewRequest = pRequest;
  335. return cbRequest;
  336. }
  337. }
  338. //+---------------------------------------------------------------------
  339. //
  340. // Member: CMallocSpy::PostRealloc
  341. //
  342. // Synopsis: Called after OLE calls IMalloc::Realloc
  343. //
  344. // Arguments: [pActual] -- Pointer to the reallocated buffer
  345. // [fSpyed] -- Whether it was allocated with a spy active
  346. //
  347. // Returns: The buffer pointer to return
  348. //
  349. // History: 24-Oct-94 Created.
  350. //
  351. // Notes:
  352. //
  353. //----------------------------------------------------------------------
  354. void *CMallocSpy::PostRealloc(void *pActual, BOOL fSpyed)
  355. {
  356. IMalloc *pmalloc;
  357. SIZE_T cbRequest;
  358. HRESULT hresult;
  359. XCHAR sz[50];
  360. if (pActual == NULL)
  361. {
  362. apLogFailInfo(XSTR("CMallocSpy::PostRealloc - Realloc of a block failed."), XSTR(""), XSTR(""), XSTR(""));
  363. return NULL;
  364. }
  365. // Return the buffer with the header offset
  366. if (fSpyed)
  367. {
  368. DelInst(m_pvRealloc);
  369. if (FAILED(hresult = CoGetMalloc(MEMCTX_TASK, &pmalloc)))
  370. {
  371. apSPrintf(sz, XSTR("%lX"), hresult);
  372. apLogFailInfo(XSTR("ERROR:CoGetMalloc failed!!!"), XSTR("NOEEROR"), sz, XSTR(""));
  373. }
  374. m_fWantTrueSize = TRUE;
  375. cbRequest = pmalloc->GetSize(pActual) - HEADERSIZE - TRAILERSIZE;
  376. m_fWantTrueSize = FALSE;
  377. pmalloc->Release();
  378. if (MEMCMP(pActual, g_rgchHead, HEADERSIZE) != 0)
  379. {
  380. MEMCPY(sz, pActual, HEADERSIZE);
  381. sz[HEADERSIZE] = 0;
  382. apLogFailInfo(XSTR("32-bit Memory header not intact!"), g_rgchHead, sz, XSTR(""));
  383. }
  384. // set new trailer signature
  385. MEMCPY((BYTE *)pActual+HEADERSIZE+cbRequest, g_rgchTail, TRAILERSIZE);
  386. // save info for leak detection
  387. AddInst((BYTE *)pActual+HEADERSIZE, cbRequest);
  388. return (void *) (((BYTE *) pActual) + HEADERSIZE);
  389. }
  390. else
  391. {
  392. return pActual;
  393. }
  394. }
  395. //+---------------------------------------------------------------------
  396. //
  397. // Member: CMallocSpy::PreGetSize
  398. //
  399. // Synopsis: Called prior to OLE calling IMalloc::GetSize
  400. //
  401. // Arguments: [pRequest] -- The buffer whose size is to be returned
  402. // [fSpyed] -- Whether it was allocated with a spy active
  403. //
  404. // Returns: The actual buffer with which to call IMalloc::GetSize
  405. //
  406. // History: 24-Oct-94 Created.
  407. //
  408. // Notes:
  409. //
  410. //----------------------------------------------------------------------
  411. void *CMallocSpy::PreGetSize(void *pRequest, BOOL fSpyed)
  412. {
  413. HeapCheck();
  414. if (fSpyed && !m_fWantTrueSize)
  415. {
  416. return (void *) (((BYTE *) pRequest) - HEADERSIZE);
  417. }
  418. else
  419. {
  420. return pRequest;
  421. }
  422. }
  423. //+---------------------------------------------------------------------
  424. //
  425. // Member: CMallocSpy::PostGetSize
  426. //
  427. // Synopsis: Called after OLE calls IMalloc::GetSize
  428. //
  429. // Arguments: [cbActual] -- The result of IMalloc::GetSize
  430. // [fSpyed] -- Whether it was allocated with a spy active
  431. //
  432. // Returns: The size to return to the IMalloc::GetSize caller
  433. //
  434. // History: 24-Oct-94 Created.
  435. //
  436. // Notes:
  437. //
  438. //----------------------------------------------------------------------
  439. SIZE_T CMallocSpy::PostGetSize(SIZE_T cbActual, BOOL fSpyed)
  440. {
  441. if (fSpyed && !m_fWantTrueSize)
  442. {
  443. return cbActual - HEADERSIZE - TRAILERSIZE;
  444. }
  445. else
  446. {
  447. return cbActual;
  448. }
  449. }
  450. //+---------------------------------------------------------------------
  451. //
  452. // Member: CMallocSpy::PreDidAlloc
  453. //
  454. // Synopsis: Called prior to OLE calling IMalloc::DidAlloc
  455. //
  456. // Arguments: [pRequest] -- The buffer whose allocation is being tested
  457. // [fSpyed] -- Whether it was allocated with a spy active
  458. //
  459. // Returns: The buffer whose allocation is actually to be tested
  460. //
  461. // History: 24-Oct-94 Created.
  462. //
  463. // Notes:
  464. //
  465. //----------------------------------------------------------------------
  466. void *CMallocSpy::PreDidAlloc(void *pRequest, BOOL fSpyed)
  467. {
  468. HeapCheck();
  469. if (fSpyed)
  470. {
  471. return (void *) (((BYTE *) pRequest) - HEADERSIZE);
  472. }
  473. else
  474. {
  475. return pRequest;
  476. }
  477. }
  478. //+---------------------------------------------------------------------
  479. //
  480. // Function: PostDidAlloc
  481. //
  482. // Synopsis: Called after OLE calls the IMalloc::DidAlloc
  483. //
  484. // Arguments: [pRequest] -- The passed allocation
  485. // [fSpyed] -- Whether it was allocated with a spy active
  486. // [fActual] -- The result of IMalloc::DidAlloc
  487. //
  488. // Returns: The result of IMalloc::DidAlloc
  489. //
  490. // History: 24-Oct-94 Created.
  491. //
  492. // Notes:
  493. //
  494. //----------------------------------------------------------------------
  495. BOOL CMallocSpy::PostDidAlloc(void * /*pRequest*/, BOOL /*fSpyed*/, BOOL fActual)
  496. {
  497. return fActual;
  498. }
  499. //+---------------------------------------------------------------------
  500. //
  501. // Member: CMallocSpy::PreHeapMinimize
  502. //
  503. // Synopsis: Called prior to OLE calling the IMalloc::HeapMinimize
  504. //
  505. // Returns:
  506. //
  507. // History: 24-Oct-94 Created.
  508. //
  509. // Notes:
  510. //
  511. //----------------------------------------------------------------------
  512. void CMallocSpy::PreHeapMinimize(void)
  513. {
  514. HeapCheck();
  515. return;
  516. }
  517. //+---------------------------------------------------------------------
  518. //
  519. // Member: CMallocSpy::PostHeapMinimize
  520. //
  521. // Synopsis: Called after OLE calls the IMalloc::HeapMinimize
  522. //
  523. // Returns:
  524. //
  525. // History: 24-Oct-94 Created.
  526. //
  527. // Notes:
  528. //
  529. //----------------------------------------------------------------------
  530. void CMallocSpy::PostHeapMinimize(void)
  531. {
  532. return;
  533. }
  534. //---------------------------------------------------------------------
  535. // Instance table methods
  536. //---------------------------------------------------------------------
  537. VOID CMallocSpy::MemInstance()
  538. {
  539. ++m_cAllocCalls;
  540. }
  541. /***
  542. *PRIVATE CMallocSpy::AddInst
  543. *Purpose:
  544. * Add the given instance to the address instance table.
  545. *
  546. *Entry:
  547. * pv = the instance to add
  548. * nAlloc = the allocation passcount of this instance
  549. *
  550. *Exit:
  551. * None
  552. *
  553. ***********************************************************************/
  554. void
  555. CMallocSpy::AddInst(void FAR* pv, SIZE_T cb)
  556. {
  557. ULONG nAlloc;
  558. UINT hash;
  559. CAddrNode32 FAR* pn;
  560. MemInstance();
  561. nAlloc = m_cAllocCalls;
  562. // DebAssert(pv != NULL, "");
  563. pn = (CAddrNode32 FAR*)new FAR CAddrNode32();
  564. // DebAssert(pn != NULL, "");
  565. pn->m_pv = pv;
  566. pn->m_cb = cb;
  567. pn->m_nAlloc = nAlloc;
  568. hash = HashInst(pv);
  569. pn->m_pnNext = m_rganode[hash];
  570. m_rganode[hash] = pn;
  571. }
  572. /***
  573. *PRIVATE CMallocSpy::DelInst(void*)
  574. *Purpose:
  575. * Remove the given instance from the address instance table.
  576. *
  577. *Entry:
  578. * pv = the instance to remove
  579. *
  580. *Exit:
  581. * None
  582. *
  583. ***********************************************************************/
  584. void
  585. CMallocSpy::DelInst(void FAR* pv)
  586. {
  587. CAddrNode32 FAR* FAR* ppn, FAR* pnDead;
  588. for(ppn = &m_rganode[HashInst(pv)]; *ppn != NULL; ppn = &(*ppn)->m_pnNext)
  589. {
  590. if((*ppn)->m_pv == pv)
  591. {
  592. pnDead = *ppn;
  593. *ppn = (*ppn)->m_pnNext;
  594. delete pnDead;
  595. return;
  596. }
  597. }
  598. // didnt find the instance
  599. // DebAssert(FALSE, "memory instance not found");
  600. }
  601. CAddrNode32 FAR*
  602. CMallocSpy::FindInst(void FAR* pv)
  603. {
  604. CAddrNode32 FAR* pn;
  605. for(pn = m_rganode[HashInst(pv)]; pn != NULL; pn = pn->m_pnNext)
  606. {
  607. if(pn->m_pv == pv)
  608. return pn;
  609. }
  610. return NULL;
  611. }
  612. void
  613. CMallocSpy::DumpInst(CAddrNode32 FAR* pn)
  614. {
  615. XCHAR szActual[128];
  616. apSPrintf(szActual, XSTR("Block of %ld bytes leaked in test"), pn->m_cb);
  617. apLogFailInfo(XSTR("Memory leaked on release of 32-bit test allocator!"), XSTR("no leak"), szActual, XSTR(""));
  618. // Printf("[%lp] nAlloc=0x%lx size=0x%lx\n", pn->m_pv, pn->m_nAlloc, pn->m_cb);
  619. }
  620. /***
  621. *PRIVATE BOOL IsEmpty
  622. *Purpose:
  623. * Answer if the address instance table is empty.
  624. *
  625. *Entry:
  626. * None
  627. *
  628. *Exit:
  629. * return value = BOOL, TRUE if empty, FALSE otherwise
  630. *
  631. ***********************************************************************/
  632. BOOL
  633. CMallocSpy::IsEmpty()
  634. {
  635. UINT u;
  636. for(u = 0; u < DIM(m_rganode); ++u)
  637. {
  638. if(m_rganode[u] != NULL) return FALSE; // something leaked
  639. }
  640. return TRUE;
  641. }
  642. /***
  643. *PRIVATE CMallocSpy::DumpInstTable()
  644. *Purpose:
  645. * Print the current contents of the address instance table,
  646. *
  647. *Entry:
  648. * None
  649. *
  650. *Exit:
  651. * None
  652. *
  653. ***********************************************************************/
  654. void
  655. CMallocSpy::DumpInstTable()
  656. {
  657. UINT u;
  658. CAddrNode32 FAR* pn;
  659. for(u = 0; u < DIM(m_rganode); ++u)
  660. {
  661. for(pn = m_rganode[u]; pn != NULL; pn = pn->m_pnNext)
  662. {
  663. VerifyHeaderTrailer(pn);
  664. DumpInst(pn);
  665. }
  666. }
  667. }
  668. /***
  669. *PRIVATE void CMallocSpy::VerifyHeaderTrailer()
  670. *Purpose:
  671. * Inspect allocations for signature overwrites.
  672. *
  673. *Entry:
  674. * None
  675. *
  676. *Exit:
  677. * return value = None.
  678. *
  679. ***********************************************************************/
  680. VOID CMallocSpy::VerifyHeaderTrailer(CAddrNode32 FAR* pn)
  681. {
  682. XCHAR sz[50];
  683. XCHAR sz2[100];
  684. if (MEMCMP((char FAR*)pn->m_pv + pn->m_cb, g_rgchTail, TRAILERSIZE) != 0)
  685. {
  686. // DumpInst(pn);
  687. MEMCPY(sz, (char FAR*)pn->m_pv + pn->m_cb, TRAILERSIZE);
  688. sz[TRAILERSIZE] = 0;
  689. apSPrintf(sz2, XSTR("32-bit memory trailer corrupt on alloc of %ld bytes"), pn->m_cb);
  690. apLogFailInfo(sz2, g_rgchTail, sz, XSTR(""));
  691. apEndTest();
  692. }
  693. if (MEMCMP((char FAR*)pn->m_pv - HEADERSIZE, g_rgchHead, HEADERSIZE) != 0)
  694. {
  695. // DumpInst(pn);
  696. MEMCPY(sz, (char FAR*)pn->m_pv - HEADERSIZE, HEADERSIZE);
  697. sz[HEADERSIZE] = 0;
  698. apSPrintf(sz2, XSTR("32-bit memory header corrupt on alloc of %ld bytes"), pn->m_cb);
  699. apLogFailInfo(sz2, g_rgchHead, sz, XSTR(""));
  700. apEndTest();
  701. }
  702. }
  703. /***
  704. *PRIVATE void CMallocSpy::HeapCheck()
  705. *Purpose:
  706. * Inspect allocations for signature overwrites.
  707. *
  708. *Entry:
  709. * None
  710. *
  711. *Exit:
  712. * return value = None.
  713. *
  714. ***********************************************************************/
  715. VOID CMallocSpy::HeapCheck()
  716. {
  717. UINT u;
  718. CAddrNode32 FAR* pn;
  719. if (m_cHeapChecks++ < g_cHeapCheckInterval)
  720. {
  721. return;
  722. }
  723. m_cHeapChecks = 0; // reset
  724. for (u = 0; u < DIM(m_rganode); ++u)
  725. {
  726. for (pn = m_rganode[u]; pn != NULL; pn = pn->m_pnNext)
  727. {
  728. VerifyHeaderTrailer(pn);
  729. }
  730. }
  731. }
  732. void
  733. CMallocSpy::CheckForLeaks()
  734. {
  735. if (!IsEmpty())
  736. {
  737. DumpInstTable();
  738. apEndTest(); // make sure a failure get recorded
  739. }
  740. }
  741. //---------------------------------------------------------------------
  742. // Helper routines
  743. //---------------------------------------------------------------------
  744. STDAPI GetMallocSpy(IMallocSpy FAR* FAR* ppmallocSpy)
  745. {
  746. *ppmallocSpy = &myMallocSpy;
  747. return NOERROR;
  748. }