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.

2698 lines
80 KiB

  1. /***
  2. *dbgheap.c - Debug CRT Heap Functions
  3. *
  4. * Copyright (c) 1988-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Defines debug versions of heap functions.
  8. *
  9. *Revision History:
  10. * 08-16-94 CFW Module created.
  11. * 11-28-94 CFW Tune up, lube, & oil change.
  12. * 12-01-94 CFW Fix debug new handler support.
  13. * 01-09-94 CFW Dump client needs size, filename pointers are const,
  14. * add _CrtSetBreakAlloc, use const state pointers.
  15. * 01-11-94 CFW Use unsigned chars.
  16. * 01-20-94 CFW Change unsigned chars to chars.
  17. * 01-24-94 CFW Cleanup: remove unneeded funcs, add way to not check
  18. * CRT blocks, add _CrtSetDbgFlag.
  19. * 01-31-94 CFW Remove zero-length block warning.
  20. * 02-09-95 CFW PMac work, remove bad _CrtSetDbgBlockType _ASSERT.
  21. * 02-24-95 CFW Fix _CrtSetBlockType for static objects.
  22. * 02-24-95 CFW Make leak messages IDE grockable.
  23. * 03-21-95 CFW Remove _CRTDBG_TRACK_ON_DF, add user-friendly block
  24. * verification macro, block damage now includes request
  25. * number, speed up client object hex dumps.
  26. * 04-06-95 CFW _expand() should handle block size == 0.
  27. * 04-19-95 CFW Don't print free blocks, fix bug in buffer check.
  28. * 03-21-95 CFW Move _BLOCK_TYPE_IS_VALID to dbgint.h
  29. * 03-24-95 CFW Fix typo in szBlockUseName.
  30. * 04-25-95 CFW Add _CRTIMP to all exported functions.
  31. * 05-01-95 GJF Gutted most of _CrtIsLocalHeap for WINHEAP build.
  32. * 05-24-95 CFW Official ANSI C++ new handler added, _CrtIsValid*Pointer.
  33. * 06-12-95 JWM HeapValidate() call removed (temporarily?) due to
  34. * performance/reliability concerns.
  35. * 06-13-95 CFW If no client dump routine available, do simple dump.
  36. * 06-21-95 CFW CRT blocks can be freed as NORMAL blocks.
  37. * 06-23-95 CFW Fix block size check.
  38. * 06-27-95 CFW Add win32s support for debug libs.
  39. * 07-15-95 CFW Fix block size check again.
  40. * 01-19-96 JWM Comments around HeapValidate() sanitized.
  41. * 01-22-96 SKS Restore HeapValidate() call in _CrtIsValidHeapPointer.
  42. * 02-14-96 SKS Remove HeapValidate() again -- but only for Win32s
  43. * 02-21-96 SKS Do NOT call HeapValidate() under Win32s -- all models!
  44. * 03-11-96 GJF Added support for small-block heap.
  45. * 04-11-96 GJF _CrtIsValidHeapPointer should return FALSE if pointer
  46. * points to a free block in the small-block heap. Also,
  47. * return type of __sbh_find_block is now __map_t *.
  48. * 04-17-96 JWM Make _CrtSetDbgBlockType() _CRTIMP (for msvcirtd.dll).
  49. * 04-25-96 GJF Don't #include <heap.h> for WINHEAP.
  50. * 05-30-96 GJF Minor changes for latest version of small-block heap.
  51. * 05-22-97 RDK Change to _CrtIsValidHeapPointer for new small-block heap.
  52. * 03-19-98 GJF Exception-safe locking.
  53. * 05-22-98 JWM Support for KFrei's RTC work.
  54. * 07-28-98 JWM RTC update.
  55. * 10-13-98 KBF RTC bug fix for _realloc_dbg
  56. * 10-27-98 JWM _crtDbgFlag now has _CRTDBG_CHECK_ALWAYS_DF set by default.
  57. * 11-05-98 JWM Removed 2 tests prone to false positives and silenced
  58. * error reporting from within CheckBytes().
  59. * 11-19-98 GJF Added support for multiple heap hack.
  60. * 11-30-98 KBF Fixed RTC bug with dbg versions of realloc and expand
  61. * 12-01-98 KBF Fixed anothe RTC bug (MC 11029) with realloc & expand
  62. * 12-01-98 GJF More choices for calling _CrtCheckMemory than never or always.
  63. * 01-05-99 GJF Changes for 64-bit size_t.
  64. * 05-12-99 PML Disable small-block heap for Win64.
  65. * 05-17-99 PML Remove all Macintosh support.
  66. * 05-17-99 PML Don't break if _lRequestCurr wraps around to -1.
  67. * 05-26-99 KBF Updated RTC_Allocate_hook & RTC_Free_hook params
  68. * 06-25-99 GJF Removed old small-block heap from static libs.
  69. * 10-06-99 PML Win64: %u to %Iu for size_t, %08X to %p for pointers.
  70. * 01-04-00 GB Debug support for _aligned routines.
  71. * 01-19-00 GB Fixed _alingned_realloc and _aligned_offset_realloc
  72. * to move the memblock while realloc.
  73. * 03-16-00 GB Fixed _aligned_offset routines for -ve values of
  74. * offset.
  75. * 03-20-00 GB Rewrite _aligned_malloc and _aligned_realloc making
  76. * use of their offset counterparts with offset=0
  77. * 05-31-00 PML Add _CrtReportBlockType (VS7#55049).
  78. * 06-21-00 GB Changed _aligned_realloc so as to mimic realloc.
  79. * 07-19-00 PML Only test header readability in _CrtIsValidHeapPointer
  80. * to avoid multi-thread corruption (VS7#129571).
  81. * 08-05-02 BWT Remove WINHEAP checks and move _HEAP_LOCK acquire/release
  82. * into heap_alloc_dbg
  83. *
  84. *******************************************************************************/
  85. #ifdef _DEBUG
  86. #include <windows.h>
  87. #include <winheap.h>
  88. #include <ctype.h>
  89. #include <dbgint.h>
  90. #include <crtdbg.h>
  91. #include <rtcsup.h>
  92. #include <internal.h>
  93. #include <limits.h>
  94. #include <malloc.h>
  95. #include <mtdll.h>
  96. #include <stdio.h>
  97. #include <stdlib.h>
  98. #include <errno.h>
  99. void * __cdecl _heap_alloc_base (size_t size);
  100. /*---------------------------------------------------------------------------
  101. *
  102. * Heap management
  103. *
  104. --------------------------------------------------------------------------*/
  105. #define IGNORE_REQ 0L /* Request number for ignore block */
  106. #define IGNORE_LINE 0xFEDCBABC /* Line number for ignore block */
  107. /*
  108. * Bitfield flag that controls CRT heap behavior --
  109. * default is to record all allocations (_CRTDBG_ALLOC_MEM_DF)
  110. * AND check heap consistency on every alloc/dealloc (_CRTDBG_CHECK_ALWAYS_DF)
  111. */
  112. int _crtDbgFlag = _CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_DEFAULT_DF;
  113. /*
  114. * struct used by _aligned routines as block header.
  115. */
  116. typedef struct _AlignMemBlockHdr
  117. {
  118. void *pHead;
  119. unsigned char Gap[nNoMansLandSize];
  120. } _AlignMemBlockHdr;
  121. #define IS_2_POW_N(x) (((x)&(x-1)) == 0)
  122. /*
  123. * Statics governing how often _CrtCheckMemory is called.
  124. */
  125. static unsigned check_frequency = _CRTDBG_CHECK_DEFAULT_DF >> 16;
  126. static unsigned check_counter;
  127. static long _lRequestCurr = 1; /* Current request number */
  128. _CRTIMP long _crtBreakAlloc = -1L; /* Break on allocation by request number */
  129. static size_t _lTotalAlloc; /* Grand total - sum of all allocations */
  130. static size_t _lCurAlloc; /* Total amount currently allocated */
  131. static size_t _lMaxAlloc; /* Largest ever allocated at once */
  132. /*
  133. * The following values are non-zero, constant, odd, large, and atypical
  134. * Non-zero values help find bugs assuming zero filled data.
  135. * Constant values are good so that memory filling is deterministic
  136. * (to help make bugs reproducable). Of course it is bad if
  137. * the constant filling of weird values masks a bug.
  138. * Mathematically odd numbers are good for finding bugs assuming a cleared
  139. * lower bit.
  140. * Large numbers (byte values at least) are less typical, and are good
  141. * at finding bad addresses.
  142. * Atypical values (i.e. not too often) are good since they typically
  143. * cause early detection in code.
  144. * For the case of no-man's land and free blocks, if you store to any
  145. * of these locations, the memory integrity checker will detect it.
  146. */
  147. static unsigned char _bNoMansLandFill = 0xFD; /* fill no-man's land with this */
  148. static unsigned char _bDeadLandFill = 0xDD; /* fill free objects with this */
  149. static unsigned char _bCleanLandFill = 0xCD; /* fill new objects with this */
  150. static unsigned char _bAlignLandFill = 0xBD; /* fill no-man's land for
  151. aligned routines */
  152. static _CrtMemBlockHeader * _pFirstBlock;
  153. static _CrtMemBlockHeader * _pLastBlock;
  154. _CRT_DUMP_CLIENT _pfnDumpClient;
  155. #if _FREE_BLOCK != 0 || _NORMAL_BLOCK != 1 || _CRT_BLOCK != 2 || _IGNORE_BLOCK != 3 || _CLIENT_BLOCK != 4 /*IFSTRIP=IGN*/
  156. #error Block numbers have changed !
  157. #endif
  158. static char * szBlockUseName[_MAX_BLOCKS] = {
  159. "Free",
  160. "Normal",
  161. "CRT",
  162. "Ignore",
  163. "Client",
  164. };
  165. int __cdecl CheckBytes(unsigned char *, unsigned char, size_t);
  166. /***
  167. *void *malloc() - Get a block of memory from the debug heap
  168. *
  169. *Purpose:
  170. * Allocate of block of memory of at least size bytes from the heap and
  171. * return a pointer to it.
  172. *
  173. * Allocates 'normal' memory block.
  174. *
  175. *Entry:
  176. * size_t nSize - size of block requested
  177. *
  178. *Exit:
  179. * Success: Pointer to memory block
  180. * Failure: NULL (or some error value)
  181. *
  182. *Exceptions:
  183. *
  184. *******************************************************************************/
  185. _CRTIMP void * __cdecl malloc (
  186. size_t nSize
  187. )
  188. {
  189. void *res = _nh_malloc_dbg(nSize, _newmode, _NORMAL_BLOCK, NULL, 0);
  190. RTCCALLBACK(_RTC_Allocate_hook, (res, nSize, 0));
  191. return res;
  192. }
  193. /***
  194. *void * _malloc_dbg() - Get a block of memory from the debug heap
  195. *
  196. *Purpose:
  197. * Allocate of block of memory of at least size bytes from the heap and
  198. * return a pointer to it.
  199. *
  200. * Allocates any type of supported memory block.
  201. *
  202. *Entry:
  203. * size_t nSize - size of block requested
  204. * int nBlockUse - block type
  205. * char * szFileName - file name
  206. * int nLine - line number
  207. *
  208. *Exit:
  209. * Success: Pointer to memory block
  210. * Failure: NULL (or some error value)
  211. *
  212. *Exceptions:
  213. *
  214. *******************************************************************************/
  215. _CRTIMP void * __cdecl _malloc_dbg (
  216. size_t nSize,
  217. int nBlockUse,
  218. const char * szFileName,
  219. int nLine
  220. )
  221. {
  222. void *res = _nh_malloc_dbg(nSize, _newmode, nBlockUse, szFileName, nLine);
  223. RTCCALLBACK(_RTC_Allocate_hook, (res, nSize, 0));
  224. return res;
  225. }
  226. /***
  227. *void * _nh_malloc() - Get a block of memory from the debug heap
  228. *
  229. *Purpose:
  230. * Allocate of block of memory of at least size bytes from the debug
  231. * heap and return a pointer to it. Assumes heap already locked.
  232. *
  233. * If no blocks available, call new handler.
  234. *
  235. * Allocates 'normal' memory block.
  236. *
  237. *Entry:
  238. * size_t nSize - size of block requested
  239. * int nhFlag - TRUE if new handler function
  240. *
  241. *Exit:
  242. * Success: Pointer to (user portion of) memory block
  243. * Failure: NULL
  244. *
  245. *Exceptions:
  246. *
  247. *******************************************************************************/
  248. void * __cdecl _nh_malloc (
  249. size_t nSize,
  250. int nhFlag
  251. )
  252. {
  253. return _nh_malloc_dbg(nSize, nhFlag, _NORMAL_BLOCK, NULL, 0);
  254. }
  255. /***
  256. *void * _nh_malloc_dbg() - Get a block of memory from the debug heap
  257. *
  258. *Purpose:
  259. * Allocate of block of memory of at least size bytes from the debug
  260. * heap and return a pointer to it. Assumes heap already locked.
  261. *
  262. * If no blocks available, call new handler.
  263. *
  264. * Allocates any type of supported memory block.
  265. *
  266. *Entry:
  267. * size_t nSize - size of block requested
  268. * int nhFlag - TRUE if new handler function
  269. * int nBlockUse - block type
  270. * char * szFileName - file name
  271. * int nLine - line number
  272. *
  273. *Exit:
  274. * Success: Pointer to (user portion of) memory block
  275. * Failure: NULL
  276. *
  277. *Exceptions:
  278. *
  279. *******************************************************************************/
  280. void * __cdecl _nh_malloc_dbg (
  281. size_t nSize,
  282. int nhFlag,
  283. int nBlockUse,
  284. const char * szFileName,
  285. int nLine
  286. )
  287. {
  288. void * pvBlk;
  289. for (;;)
  290. {
  291. /* do the allocation
  292. */
  293. pvBlk = _heap_alloc_dbg(nSize, nBlockUse, szFileName, nLine);
  294. if (pvBlk || nhFlag == 0)
  295. return pvBlk;
  296. /* call installed new handler */
  297. if (!_callnewh(nSize))
  298. return NULL;
  299. /* new handler was successful -- try to allocate again */
  300. }
  301. }
  302. /***
  303. *void * _heap_alloc() - does actual allocation
  304. *
  305. *Purpose:
  306. * Does heap allocation.
  307. *
  308. * Allocates 'normal' memory block.
  309. *
  310. *Entry:
  311. * size_t nSize - size of block requested
  312. *
  313. *Exit:
  314. * Success: Pointer to (user portion of) memory block
  315. * Failure: NULL
  316. *
  317. *Exceptions:
  318. *
  319. *******************************************************************************/
  320. void * __cdecl _heap_alloc(
  321. size_t nSize
  322. )
  323. {
  324. return _heap_alloc_dbg(nSize, _NORMAL_BLOCK, NULL, 0);
  325. }
  326. /***
  327. *void * _heap_alloc_dbg() - does actual allocation
  328. *
  329. *Purpose:
  330. * Does heap allocation.
  331. *
  332. * Allocates any type of supported memory block.
  333. *
  334. *Entry:
  335. * size_t nSize - size of block requested
  336. * int nBlockUse - block type
  337. * char * szFileName - file name
  338. * int nLine - line number
  339. *
  340. *Exit:
  341. * Success: Pointer to (user portion of) memory block
  342. * Failure: NULL
  343. *
  344. *Exceptions:
  345. *
  346. *******************************************************************************/
  347. void * __cdecl _heap_alloc_dbg(
  348. size_t nSize,
  349. int nBlockUse,
  350. const char * szFileName,
  351. int nLine
  352. )
  353. {
  354. long lRequest;
  355. size_t blockSize;
  356. int fIgnore = FALSE;
  357. _CrtMemBlockHeader * pHead;
  358. #ifdef _MT
  359. /* lock the heap
  360. */
  361. _mlock(_HEAP_LOCK);
  362. __try {
  363. #endif
  364. /* verify heap before allocation */
  365. if (check_frequency > 0)
  366. if (check_counter == (check_frequency - 1))
  367. {
  368. _ASSERTE(_CrtCheckMemory());
  369. check_counter = 0;
  370. }
  371. else
  372. check_counter++;
  373. lRequest = _lRequestCurr;
  374. /* break into debugger at specific memory allocation */
  375. if (_crtBreakAlloc != -1L && lRequest == _crtBreakAlloc)
  376. _CrtDbgBreak();
  377. /* forced failure */
  378. if (!(*_pfnAllocHook)(_HOOK_ALLOC, NULL, nSize, nBlockUse, lRequest, szFileName, nLine))
  379. {
  380. if (szFileName)
  381. _RPT2(_CRT_WARN, "Client hook allocation failure at file %hs line %d.\n",
  382. szFileName, nLine);
  383. else
  384. _RPT0(_CRT_WARN, "Client hook allocation failure.\n");
  385. return NULL;
  386. }
  387. /* cannot ignore CRT allocations */
  388. if (_BLOCK_TYPE(nBlockUse) != _CRT_BLOCK &&
  389. !(_crtDbgFlag & _CRTDBG_ALLOC_MEM_DF))
  390. fIgnore = TRUE;
  391. /* Diagnostic memory allocation from this point on */
  392. if (nSize > (size_t)_HEAP_MAXREQ ||
  393. nSize + nNoMansLandSize + sizeof(_CrtMemBlockHeader) > (size_t)_HEAP_MAXREQ)
  394. {
  395. _RPT1(_CRT_ERROR, "Invalid allocation size: %Iu bytes.\n", nSize);
  396. return NULL;
  397. }
  398. if (!_BLOCK_TYPE_IS_VALID(nBlockUse))
  399. {
  400. _RPT0(_CRT_ERROR, "Error: memory allocation: bad memory block type.\n");
  401. }
  402. blockSize = sizeof(_CrtMemBlockHeader) + nSize + nNoMansLandSize;
  403. RTCCALLBACK(_RTC_FuncCheckSet_hook,(0));
  404. pHead = (_CrtMemBlockHeader *)_heap_alloc_base(blockSize);
  405. if (pHead == NULL)
  406. {
  407. RTCCALLBACK(_RTC_FuncCheckSet_hook,(1));
  408. return NULL;
  409. }
  410. /* commit allocation */
  411. ++_lRequestCurr;
  412. if (fIgnore)
  413. {
  414. pHead->pBlockHeaderNext = NULL;
  415. pHead->pBlockHeaderPrev = NULL;
  416. pHead->szFileName = NULL;
  417. pHead->nLine = IGNORE_LINE;
  418. pHead->nDataSize = nSize;
  419. pHead->nBlockUse = _IGNORE_BLOCK;
  420. pHead->lRequest = IGNORE_REQ;
  421. }
  422. else {
  423. /* keep track of total amount of memory allocated */
  424. _lTotalAlloc += nSize;
  425. _lCurAlloc += nSize;
  426. if (_lCurAlloc > _lMaxAlloc)
  427. _lMaxAlloc = _lCurAlloc;
  428. if (_pFirstBlock)
  429. _pFirstBlock->pBlockHeaderPrev = pHead;
  430. else
  431. _pLastBlock = pHead;
  432. pHead->pBlockHeaderNext = _pFirstBlock;
  433. pHead->pBlockHeaderPrev = NULL;
  434. pHead->szFileName = (char *)szFileName;
  435. pHead->nLine = nLine;
  436. pHead->nDataSize = nSize;
  437. pHead->nBlockUse = nBlockUse;
  438. pHead->lRequest = lRequest;
  439. /* link blocks together */
  440. _pFirstBlock = pHead;
  441. }
  442. /* fill in gap before and after real block */
  443. memset((void *)pHead->gap, _bNoMansLandFill, nNoMansLandSize);
  444. memset((void *)(pbData(pHead) + nSize), _bNoMansLandFill, nNoMansLandSize);
  445. /* fill data with silly value (but non-zero) */
  446. memset((void *)pbData(pHead), _bCleanLandFill, nSize);
  447. RTCCALLBACK(_RTC_FuncCheckSet_hook,(1));
  448. #ifdef _MT
  449. }
  450. __finally {
  451. /* unlock the heap
  452. */
  453. _munlock(_HEAP_LOCK);
  454. }
  455. #endif
  456. return (void *)pbData(pHead);
  457. }
  458. /***
  459. *void * calloc() - Get a block of memory from the debug heap, init to 0
  460. *
  461. *Purpose:
  462. * Allocate of block of memory of at least size bytes from the debug
  463. * heap and return a pointer to it.
  464. *
  465. * Allocates 'normal' memory block.
  466. *
  467. *Entry:
  468. * size_t nNum - number of elements in the array
  469. * size_t nSize - size of each element
  470. *
  471. *Exit:
  472. * Success: Pointer to (user portion of) memory block
  473. * Failure: NULL
  474. *
  475. *Exceptions:
  476. *
  477. *******************************************************************************/
  478. _CRTIMP void * __cdecl calloc(
  479. size_t nNum,
  480. size_t nSize
  481. )
  482. {
  483. void *res = _calloc_dbg(nNum, nSize, _NORMAL_BLOCK, NULL, 0);
  484. RTCCALLBACK(_RTC_Allocate_hook, (res, nNum * nSize, 0));
  485. return res;
  486. }
  487. /***
  488. *void * _calloc_dbg() - Get a block of memory from the debug heap, init to 0
  489. * - with info
  490. *
  491. *Purpose:
  492. * Allocate of block of memory of at least size bytes from the debug
  493. * heap and return a pointer to it.
  494. *
  495. * Allocates any type of supported memory block.
  496. *
  497. *Entry:
  498. * size_t nNum - number of elements in the array
  499. * size_t nSize - size of each element
  500. * int nBlockUse - block type
  501. * char * szFileName - file name
  502. * int nLine - line number
  503. *
  504. *Exit:
  505. * Success: Pointer to (user portion of) memory block
  506. * Failure: NULL
  507. *
  508. *Exceptions:
  509. *
  510. *******************************************************************************/
  511. _CRTIMP void * __cdecl _calloc_dbg(
  512. size_t nNum,
  513. size_t nSize,
  514. int nBlockUse,
  515. const char * szFileName,
  516. int nLine
  517. )
  518. {
  519. void * pvBlk;
  520. unsigned char *pStart;
  521. unsigned char *pLast;
  522. nSize *= nNum;
  523. /*
  524. * try to malloc the requested space
  525. */
  526. pvBlk = _malloc_dbg(nSize, nBlockUse, szFileName, nLine);
  527. /*
  528. * If malloc() succeeded, initialize the allocated space to zeros.
  529. * Note that unlike _calloc_base, exactly nNum bytes are set to zero.
  530. */
  531. if ( pvBlk != NULL )
  532. {
  533. pStart = (unsigned char *)pvBlk;
  534. pLast = pStart + nSize;
  535. while ( pStart < pLast )
  536. *(pStart++) = 0;
  537. }
  538. RTCCALLBACK(_RTC_Allocate_hook, (pvBlk, nSize, 0));
  539. return(pvBlk);
  540. }
  541. /***
  542. *static void * realloc_help() - does all the work for _realloc and _expand
  543. *
  544. *Purpose:
  545. * Helper function for _realloc and _expand.
  546. *
  547. *Entry:
  548. * void * pUserData - pointer previously allocated block
  549. * size_t nNewSize - requested size for the re-allocated block
  550. * int nBlockUse - block type
  551. * char * szFileName - file name
  552. * int nLine - line number
  553. * int fRealloc - TRUE when _realloc, FALSE when _expand
  554. *
  555. *Exit:
  556. * Success: Pointer to (user portion of) memory block
  557. * Failure: NULL
  558. *
  559. *Exceptions:
  560. *
  561. *******************************************************************************/
  562. static void * __cdecl realloc_help(
  563. void * pUserData,
  564. size_t nNewSize,
  565. int nBlockUse,
  566. const char * szFileName,
  567. int nLine,
  568. int fRealloc
  569. )
  570. {
  571. long lRequest;
  572. int fIgnore = FALSE;
  573. unsigned char *pUserBlock;
  574. _CrtMemBlockHeader * pOldBlock;
  575. _CrtMemBlockHeader * pNewBlock;
  576. /*
  577. * ANSI: realloc(NULL, newsize) is equivalent to malloc(newsize)
  578. */
  579. if (pUserData == NULL)
  580. {
  581. return _malloc_dbg(nNewSize, nBlockUse, szFileName, nLine);
  582. }
  583. /*
  584. * ANSI: realloc(pUserData, 0) is equivalent to free(pUserData)
  585. * (except that NULL is returned)
  586. */
  587. if (fRealloc && nNewSize == 0)
  588. {
  589. _free_dbg(pUserData, nBlockUse);
  590. return NULL;
  591. }
  592. /* verify heap before re-allocation */
  593. if (check_frequency > 0)
  594. if (check_counter == (check_frequency - 1))
  595. {
  596. _ASSERTE(_CrtCheckMemory());
  597. check_counter = 0;
  598. }
  599. else
  600. check_counter++;
  601. lRequest = _lRequestCurr;
  602. if (_crtBreakAlloc != -1L && lRequest == _crtBreakAlloc)
  603. _CrtDbgBreak(); /* break into debugger at specific memory leak */
  604. /* forced failure */
  605. if (!(*_pfnAllocHook)(_HOOK_REALLOC, pUserData, nNewSize, nBlockUse, lRequest, szFileName, nLine))
  606. {
  607. if (szFileName)
  608. _RPT2(_CRT_WARN, "Client hook re-allocation failure at file %hs line %d.\n",
  609. szFileName, nLine);
  610. else
  611. _RPT0(_CRT_WARN, "Client hook re-allocation failure.\n");
  612. return NULL;
  613. }
  614. /* Diagnostic memory allocation from this point on */
  615. if (nNewSize > (size_t)UINT_MAX - nNoMansLandSize - sizeof(_CrtMemBlockHeader))
  616. {
  617. _RPT1(_CRT_ERROR, "Allocation too large or negative: %Iu bytes.\n",
  618. nNewSize);
  619. return NULL;
  620. }
  621. if (nBlockUse != _NORMAL_BLOCK
  622. && _BLOCK_TYPE(nBlockUse) != _CLIENT_BLOCK
  623. && _BLOCK_TYPE(nBlockUse) != _CRT_BLOCK)
  624. {
  625. _RPT0(_CRT_ERROR, "Error: memory allocation: bad memory block type.\n");
  626. } else
  627. {
  628. if ( CheckBytes((unsigned char*)((uintptr_t)pUserData & ~(sizeof(uintptr_t) -1)) -nNoMansLandSize,_bAlignLandFill, nNoMansLandSize))
  629. {
  630. _RPT1(_CRT_ERROR, "The Block at 0x%p was allocated by aligned routines, use _aligned_realloc()", pUserData);
  631. return NULL;
  632. }
  633. }
  634. /*
  635. * If this ASSERT fails, a bad pointer has been passed in. It may be
  636. * totally bogus, or it may have been allocated from another heap.
  637. * The pointer MUST come from the 'local' heap.
  638. */
  639. _ASSERTE(_CrtIsValidHeapPointer(pUserData));
  640. /* get a pointer to memory block header */
  641. pOldBlock = pHdr(pUserData);
  642. if (pOldBlock->nBlockUse == _IGNORE_BLOCK)
  643. fIgnore = TRUE;
  644. if (fIgnore)
  645. {
  646. _ASSERTE(pOldBlock->nLine == IGNORE_LINE && pOldBlock->lRequest == IGNORE_REQ);
  647. }
  648. else {
  649. /* Error if freeing incorrect memory type */
  650. /* CRT blocks can be treated as NORMAL blocks */
  651. if (_BLOCK_TYPE(pOldBlock->nBlockUse) == _CRT_BLOCK && _BLOCK_TYPE(nBlockUse) == _NORMAL_BLOCK)
  652. nBlockUse = _CRT_BLOCK;
  653. /* The following assertion was prone to false positives - JWM */
  654. /* _ASSERTE(_BLOCK_TYPE(pOldBlock->nBlockUse)==_BLOCK_TYPE(nBlockUse)); */
  655. }
  656. /*
  657. * note that all header values will remain valid
  658. * and min(nNewSize,nOldSize) bytes of data will also remain valid
  659. */
  660. RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
  661. RTCCALLBACK(_RTC_FuncCheckSet_hook,(0));
  662. if (fRealloc)
  663. {
  664. if (NULL == (pNewBlock = _realloc_base(pOldBlock,
  665. sizeof(_CrtMemBlockHeader) + nNewSize + nNoMansLandSize)))
  666. {
  667. RTCCALLBACK(_RTC_FuncCheckSet_hook,(1));
  668. return NULL;
  669. }
  670. }
  671. else {
  672. if (NULL == (pNewBlock = _expand_base(pOldBlock,
  673. sizeof(_CrtMemBlockHeader) + nNewSize + nNoMansLandSize)))
  674. {
  675. RTCCALLBACK(_RTC_FuncCheckSet_hook,(1));
  676. return NULL;
  677. }
  678. }
  679. /* commit allocation */
  680. ++_lRequestCurr;
  681. if (!fIgnore)
  682. {
  683. /* keep track of total amount of memory allocated */
  684. _lTotalAlloc -= pNewBlock->nDataSize;
  685. _lTotalAlloc += nNewSize;
  686. _lCurAlloc -= pNewBlock->nDataSize;
  687. _lCurAlloc += nNewSize;
  688. if (_lCurAlloc > _lMaxAlloc)
  689. _lMaxAlloc = _lCurAlloc;
  690. }
  691. // Free this thing from RTC - it will be reallocated a bit later (inside realloc_dbg/expand_dbg)
  692. RTCCALLBACK(_RTC_Free_hook, (pNewBlock, 0));
  693. pUserBlock = pbData(pNewBlock);
  694. /* if the block grew, put in special value */
  695. if (nNewSize > pNewBlock->nDataSize)
  696. memset(pUserBlock + pNewBlock->nDataSize, _bCleanLandFill,
  697. nNewSize - pNewBlock->nDataSize);
  698. /* fill in gap after real block */
  699. memset(pUserBlock + nNewSize, _bNoMansLandFill, nNoMansLandSize);
  700. if (!fIgnore)
  701. {
  702. pNewBlock->szFileName = (char *)szFileName;
  703. pNewBlock->nLine = nLine;
  704. pNewBlock->lRequest = lRequest;
  705. }
  706. pNewBlock->nDataSize = nNewSize;
  707. _ASSERTE(fRealloc || (!fRealloc && pNewBlock == pOldBlock));
  708. RTCCALLBACK(_RTC_FuncCheckSet_hook,(1));
  709. /* if block did not move or ignored, we are done */
  710. if (pNewBlock == pOldBlock || fIgnore)
  711. return (void *)pUserBlock;
  712. /* must remove old memory from dbg heap list */
  713. /* note that new block header pointers still valid */
  714. if (pNewBlock->pBlockHeaderNext)
  715. {
  716. pNewBlock->pBlockHeaderNext->pBlockHeaderPrev
  717. = pNewBlock->pBlockHeaderPrev;
  718. }
  719. else
  720. {
  721. _ASSERTE(_pLastBlock == pOldBlock);
  722. _pLastBlock = pNewBlock->pBlockHeaderPrev;
  723. }
  724. if (pNewBlock->pBlockHeaderPrev)
  725. {
  726. pNewBlock->pBlockHeaderPrev->pBlockHeaderNext
  727. = pNewBlock->pBlockHeaderNext;
  728. }
  729. else
  730. {
  731. _ASSERTE(_pFirstBlock == pOldBlock);
  732. _pFirstBlock = pNewBlock->pBlockHeaderNext;
  733. }
  734. /* put new memory into list */
  735. if (_pFirstBlock)
  736. _pFirstBlock->pBlockHeaderPrev = pNewBlock;
  737. else
  738. _pLastBlock = pNewBlock;
  739. pNewBlock->pBlockHeaderNext = _pFirstBlock;
  740. pNewBlock->pBlockHeaderPrev = NULL;
  741. /* link blocks together */
  742. _pFirstBlock = pNewBlock;
  743. return (void *)pUserBlock;
  744. }
  745. /***
  746. *void * realloc() - reallocate a block of memory in the heap
  747. *
  748. *Purpose:
  749. * Re-allocates a block in the heap to nNewSize bytes. nNewSize may be
  750. * either greater or less than the original size of the block. The
  751. * re-allocation may result in moving the block as well as changing
  752. * the size. If the block is moved, the contents of the original block
  753. * are copied over.
  754. *
  755. * Re-allocates 'normal' memory block.
  756. *
  757. *Entry:
  758. * void * pUserData - pointer to previously allocated block
  759. * size_t nNewSize - requested size for the re-allocated block
  760. *
  761. *Exit:
  762. * Success: Pointer to (user portion of) memory block
  763. * Failure: NULL
  764. *
  765. *Exceptions:
  766. *
  767. *******************************************************************************/
  768. _CRTIMP void * __cdecl realloc(
  769. void * pUserData,
  770. size_t nNewSize
  771. )
  772. {
  773. void *res = _realloc_dbg(pUserData, nNewSize, _NORMAL_BLOCK, NULL, 0);
  774. if (res)
  775. RTCCALLBACK(_RTC_Allocate_hook, (res, nNewSize, 0));
  776. return res;
  777. }
  778. /***
  779. *void * _realloc_dbg() - reallocate a block of memory in the heap
  780. * - with info
  781. *
  782. *Purpose:
  783. * Re-allocates a block in the heap to nNewSize bytes. nNewSize may be
  784. * either greater or less than the original size of the block. The
  785. * re-allocation may result in moving the block as well as changing
  786. * the size. If the block is moved, the contents of the original block
  787. * are copied over.
  788. *
  789. * Re-allocates any type of supported memory block.
  790. *
  791. *Entry:
  792. * void * pUserData - pointer previously allocated block
  793. * size_t nNewSize - requested size for the re-allocated block
  794. * int nBlockUse - block type
  795. * char * szFileName - file name
  796. * int nLine - line number
  797. *
  798. *Exit:
  799. * Success: Pointer to (user portion of) memory block
  800. * Failure: NULL
  801. *
  802. *Exceptions:
  803. *
  804. *******************************************************************************/
  805. _CRTIMP void * __cdecl _realloc_dbg(
  806. void * pUserData,
  807. size_t nNewSize,
  808. int nBlockUse,
  809. const char * szFileName,
  810. int nLine
  811. )
  812. {
  813. void * pvBlk;
  814. #ifdef _MT
  815. _mlock(_HEAP_LOCK); /* block other threads */
  816. __try {
  817. #endif
  818. /* allocate the block
  819. */
  820. pvBlk = realloc_help(pUserData,
  821. nNewSize,
  822. nBlockUse,
  823. szFileName,
  824. nLine,
  825. TRUE);
  826. #ifdef _MT
  827. }
  828. __finally {
  829. _munlock(_HEAP_LOCK); /* release other threads */
  830. }
  831. #endif
  832. if (pvBlk)
  833. {
  834. RTCCALLBACK(_RTC_Allocate_hook, (pvBlk, nNewSize, 0));
  835. }
  836. return pvBlk;
  837. }
  838. /***
  839. *void * _expand() - expand/contract a block of memory in the heap
  840. *
  841. *Purpose:
  842. * Resizes a block in the heap to newsize bytes. newsize may be either
  843. * greater (expansion) or less (contraction) than the original size of
  844. * the block. The block is NOT moved. In the case of expansion, if the
  845. * block cannot be expanded to newsize bytes, it is expanded as much as
  846. * possible.
  847. *
  848. * Re-allocates 'normal' memory block.
  849. *
  850. *Entry:
  851. * void * pUserData - pointer to block in the heap previously allocated
  852. * by a call to malloc(), realloc() or _expand().
  853. *
  854. * size_t nNewSize - requested size for the resized block
  855. *
  856. *Exit:
  857. * Success: Pointer to the resized memory block (i.e., pUserData)
  858. * Failure: NULL
  859. *
  860. *Uses:
  861. *
  862. *Exceptions:
  863. * If pUserData does not point to a valid allocation block in the heap,
  864. * _expand() will behave unpredictably and probably corrupt the heap.
  865. *
  866. *******************************************************************************/
  867. _CRTIMP void * __cdecl _expand(
  868. void * pUserData,
  869. size_t nNewSize
  870. )
  871. {
  872. void *res = _expand_dbg(pUserData, nNewSize, _NORMAL_BLOCK, NULL, 0);
  873. if (res)
  874. RTCCALLBACK(_RTC_Allocate_hook, (pUserData, nNewSize, 0));
  875. return res;
  876. }
  877. /***
  878. *void * _expand() - expand/contract a block of memory in the heap
  879. *
  880. *Purpose:
  881. * Resizes a block in the heap to newsize bytes. newsize may be either
  882. * greater (expansion) or less (contraction) than the original size of
  883. * the block. The block is NOT moved. In the case of expansion, if the
  884. * block cannot be expanded to newsize bytes, it is expanded as much as
  885. * possible.
  886. *
  887. * Re-allocates any type of supported memory block.
  888. *
  889. *Entry:
  890. * void * pUserData - pointer to block in the heap previously allocated
  891. * by a call to malloc(), realloc() or _expand().
  892. *
  893. * size_t nNewSize - requested size for the resized block
  894. *
  895. *Exit:
  896. * Success: Pointer to the resized memory block (i.e., pUserData)
  897. * Failure: NULL
  898. *
  899. *Uses:
  900. *
  901. *Exceptions:
  902. * If pUserData does not point to a valid allocation block in the heap,
  903. * _expand() will behave unpredictably and probably corrupt the heap.
  904. *
  905. *******************************************************************************/
  906. _CRTIMP void * __cdecl _expand_dbg(
  907. void * pUserData,
  908. size_t nNewSize,
  909. int nBlockUse,
  910. const char * szFileName,
  911. int nLine
  912. )
  913. {
  914. void * pvBlk;
  915. #ifdef _MT
  916. _mlock(_HEAP_LOCK); /* block other threads */
  917. __try {
  918. #endif
  919. /* allocate the block
  920. */
  921. pvBlk = realloc_help(pUserData,
  922. nNewSize,
  923. nBlockUse,
  924. szFileName,
  925. nLine,
  926. FALSE);
  927. #ifdef _MT
  928. }
  929. __finally {
  930. _munlock(_HEAP_LOCK); /* release other threads */
  931. }
  932. #endif
  933. if (pvBlk)
  934. {
  935. RTCCALLBACK(_RTC_Allocate_hook, (pUserData, nNewSize, 0));
  936. }
  937. return pvBlk;
  938. }
  939. /***
  940. *void free() - free a block in the debug heap
  941. *
  942. *Purpose:
  943. * Frees a 'normal' memory block.
  944. *
  945. *Entry:
  946. * void * pUserData - pointer to a (user portion) of memory block in the
  947. * debug heap
  948. *
  949. *Return:
  950. * <void>
  951. *
  952. *******************************************************************************/
  953. _CRTIMP void __cdecl free(
  954. void * pUserData
  955. )
  956. {
  957. _free_dbg(pUserData, _NORMAL_BLOCK);
  958. }
  959. #ifdef _MT
  960. void __cdecl _free_lk(
  961. void * pUserData
  962. )
  963. {
  964. _free_dbg_lk(pUserData, _NORMAL_BLOCK);
  965. }
  966. #endif /* _MT */
  967. /***
  968. *void _free_dbg() - free a block in the debug heap
  969. *
  970. *Purpose:
  971. * Frees any type of supported block.
  972. *
  973. *Entry:
  974. * void * pUserData - pointer to a (user portion) of memory block in the
  975. * debug heap
  976. * int nBlockUse - block type
  977. *
  978. *Return:
  979. * <void>
  980. *
  981. *******************************************************************************/
  982. #ifdef _MT
  983. _CRTIMP void __cdecl _free_dbg(
  984. void * pUserData,
  985. int nBlockUse
  986. )
  987. {
  988. /* lock the heap
  989. */
  990. _mlock(_HEAP_LOCK);
  991. __try {
  992. /* allocate the block
  993. */
  994. _free_dbg_lk(pUserData, nBlockUse);
  995. }
  996. __finally {
  997. /* unlock the heap
  998. */
  999. _munlock(_HEAP_LOCK);
  1000. }
  1001. }
  1002. void __cdecl _free_dbg_lk(
  1003. #else /* ndef _MT */
  1004. _CRTIMP void __cdecl _free_dbg(
  1005. #endif /* _MT */
  1006. void * pUserData,
  1007. int nBlockUse
  1008. )
  1009. {
  1010. _CrtMemBlockHeader * pHead;
  1011. RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
  1012. /* verify heap before freeing */
  1013. if (check_frequency > 0)
  1014. if (check_counter == (check_frequency - 1))
  1015. {
  1016. _ASSERTE(_CrtCheckMemory());
  1017. check_counter = 0;
  1018. }
  1019. else
  1020. check_counter++;
  1021. if (pUserData == NULL)
  1022. return;
  1023. /* check if the heap was not allocated by _aligned routines */
  1024. if ( nBlockUse == _NORMAL_BLOCK)
  1025. {
  1026. if ( CheckBytes((unsigned char*)((uintptr_t)pUserData & ~(sizeof(uintptr_t) -1)) -nNoMansLandSize,_bAlignLandFill, nNoMansLandSize))
  1027. {
  1028. _RPT1(_CRT_ERROR, "The Block at 0x%p was allocated by aligned routines, use _aligned_free()", pUserData);
  1029. return;
  1030. }
  1031. }
  1032. /* forced failure */
  1033. if (!(*_pfnAllocHook)(_HOOK_FREE, pUserData, 0, nBlockUse, 0L, NULL, 0))
  1034. {
  1035. _RPT0(_CRT_WARN, "Client hook free failure.\n");
  1036. return;
  1037. }
  1038. /*
  1039. * If this ASSERT fails, a bad pointer has been passed in. It may be
  1040. * totally bogus, or it may have been allocated from another heap.
  1041. * The pointer MUST come from the 'local' heap.
  1042. */
  1043. _ASSERTE(_CrtIsValidHeapPointer(pUserData));
  1044. /* get a pointer to memory block header */
  1045. pHead = pHdr(pUserData);
  1046. /* verify block type */
  1047. _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
  1048. /* if we didn't already check entire heap, at least check this object */
  1049. if (!(_crtDbgFlag & _CRTDBG_CHECK_ALWAYS_DF))
  1050. {
  1051. /* check no-mans-land gaps */
  1052. if (!CheckBytes(pHead->gap, _bNoMansLandFill, nNoMansLandSize))
  1053. _RPT3(_CRT_ERROR, "DAMAGE: before %hs block (#%d) at 0x%p.\n",
  1054. szBlockUseName[_BLOCK_TYPE(pHead->nBlockUse)],
  1055. pHead->lRequest,
  1056. (BYTE *) pbData(pHead));
  1057. if (!CheckBytes(pbData(pHead) + pHead->nDataSize, _bNoMansLandFill, nNoMansLandSize))
  1058. _RPT3(_CRT_ERROR, "DAMAGE: after %hs block (#%d) at 0x%p.\n",
  1059. szBlockUseName[_BLOCK_TYPE(pHead->nBlockUse)],
  1060. pHead->lRequest,
  1061. (BYTE *) pbData(pHead));
  1062. }
  1063. RTCCALLBACK(_RTC_FuncCheckSet_hook,(0));
  1064. if (pHead->nBlockUse == _IGNORE_BLOCK)
  1065. {
  1066. _ASSERTE(pHead->nLine == IGNORE_LINE && pHead->lRequest == IGNORE_REQ);
  1067. /* fill the entire block including header with dead-land-fill */
  1068. memset(pHead, _bDeadLandFill,
  1069. sizeof(_CrtMemBlockHeader) + pHead->nDataSize + nNoMansLandSize);
  1070. _free_base(pHead);
  1071. RTCCALLBACK(_RTC_FuncCheckSet_hook,(1));
  1072. return;
  1073. }
  1074. /* CRT blocks can be freed as NORMAL blocks */
  1075. if (pHead->nBlockUse == _CRT_BLOCK && nBlockUse == _NORMAL_BLOCK)
  1076. nBlockUse = _CRT_BLOCK;
  1077. /* Error if freeing incorrect memory type */
  1078. _ASSERTE(pHead->nBlockUse == nBlockUse);
  1079. /* keep track of total amount of memory allocated */
  1080. _lCurAlloc -= pHead->nDataSize;
  1081. /* optionally reclaim memory */
  1082. if (!(_crtDbgFlag & _CRTDBG_DELAY_FREE_MEM_DF))
  1083. {
  1084. /* remove from the linked list */
  1085. if (pHead->pBlockHeaderNext)
  1086. {
  1087. pHead->pBlockHeaderNext->pBlockHeaderPrev = pHead->pBlockHeaderPrev;
  1088. }
  1089. else
  1090. {
  1091. _ASSERTE(_pLastBlock == pHead);
  1092. _pLastBlock = pHead->pBlockHeaderPrev;
  1093. }
  1094. if (pHead->pBlockHeaderPrev)
  1095. {
  1096. pHead->pBlockHeaderPrev->pBlockHeaderNext = pHead->pBlockHeaderNext;
  1097. }
  1098. else
  1099. {
  1100. _ASSERTE(_pFirstBlock == pHead);
  1101. _pFirstBlock = pHead->pBlockHeaderNext;
  1102. }
  1103. /* fill the entire block including header with dead-land-fill */
  1104. memset(pHead, _bDeadLandFill,
  1105. sizeof(_CrtMemBlockHeader) + pHead->nDataSize + nNoMansLandSize);
  1106. _free_base(pHead);
  1107. }
  1108. else
  1109. {
  1110. pHead->nBlockUse = _FREE_BLOCK;
  1111. /* keep memory around as dead space */
  1112. memset(pbData(pHead), _bDeadLandFill, pHead->nDataSize);
  1113. }
  1114. RTCCALLBACK(_RTC_FuncCheckSet_hook,(1));
  1115. }
  1116. /***
  1117. *size_t _msize() - calculate the size of specified block in the heap
  1118. *
  1119. *Purpose:
  1120. * Calculates the size of memory block (in the heap) pointed to by
  1121. * pUserData.
  1122. *
  1123. * For 'normal' memory block.
  1124. *
  1125. *Entry:
  1126. * void * pUserData - pointer to a memory block in the heap
  1127. *
  1128. *Return:
  1129. * size of the block
  1130. *
  1131. *******************************************************************************/
  1132. _CRTIMP size_t __cdecl _msize (
  1133. void * pUserData
  1134. )
  1135. {
  1136. return _msize_dbg(pUserData, _NORMAL_BLOCK);
  1137. }
  1138. /***
  1139. *size_t _msize_dbg() - calculate the size of specified block in the heap
  1140. *
  1141. *Purpose:
  1142. * Calculates the size of memory block (in the heap) pointed to by
  1143. * pUserData.
  1144. *
  1145. *Entry:
  1146. * void * pUserData - pointer to a (user portion) of memory block in the
  1147. * debug heap
  1148. * int nBlockUse - block type
  1149. *
  1150. * For any type of supported block.
  1151. *
  1152. *Return:
  1153. * size of the block
  1154. *
  1155. *******************************************************************************/
  1156. _CRTIMP size_t __cdecl _msize_dbg (
  1157. void * pUserData,
  1158. int nBlockUse
  1159. )
  1160. {
  1161. size_t nSize;
  1162. _CrtMemBlockHeader * pHead;
  1163. /* verify heap before getting size */
  1164. if (check_frequency > 0)
  1165. if (check_counter == (check_frequency - 1))
  1166. {
  1167. _ASSERTE(_CrtCheckMemory());
  1168. check_counter = 0;
  1169. }
  1170. else
  1171. check_counter++;
  1172. #ifdef _MT
  1173. _mlock(_HEAP_LOCK); /* block other threads */
  1174. __try {
  1175. #endif
  1176. /*
  1177. * If this ASSERT fails, a bad pointer has been passed in. It may be
  1178. * totally bogus, or it may have been allocated from another heap.
  1179. * The pointer MUST come from the 'local' heap.
  1180. */
  1181. _ASSERTE(_CrtIsValidHeapPointer(pUserData));
  1182. /* get a pointer to memory block header */
  1183. pHead = pHdr(pUserData);
  1184. /* verify block type */
  1185. _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
  1186. /* CRT blocks can be treated as NORMAL blocks */
  1187. if (pHead->nBlockUse == _CRT_BLOCK && nBlockUse == _NORMAL_BLOCK)
  1188. nBlockUse = _CRT_BLOCK;
  1189. /* The following assertion was prone to false positives - JWM */
  1190. /* if (pHead->nBlockUse != _IGNORE_BLOCK) */
  1191. /* _ASSERTE(pHead->nBlockUse == nBlockUse); */
  1192. nSize = pHead->nDataSize;
  1193. #ifdef _MT
  1194. }
  1195. __finally {
  1196. _munlock(_HEAP_LOCK); /* release other threads */
  1197. }
  1198. #endif
  1199. return nSize;
  1200. }
  1201. /***
  1202. *long _CrtSetBreakAlloc() - set allocation on which to break
  1203. *
  1204. *Purpose:
  1205. * set allocation on which to break
  1206. *
  1207. *Entry:
  1208. * long lBreakAlloc
  1209. *
  1210. *Exit:
  1211. * return previous break number
  1212. *
  1213. *Exceptions:
  1214. *
  1215. *******************************************************************************/
  1216. _CRTIMP long __cdecl _CrtSetBreakAlloc(
  1217. long lNewBreakAlloc
  1218. )
  1219. {
  1220. long lOldBreakAlloc = _crtBreakAlloc;
  1221. _crtBreakAlloc = lNewBreakAlloc;
  1222. return lOldBreakAlloc;
  1223. }
  1224. /***
  1225. *void _CrtSetDbgBlockType() - change memory block type
  1226. *
  1227. *Purpose:
  1228. * change memory block type
  1229. *
  1230. *Entry:
  1231. * void * pUserData - pointer to a (user portion) of memory block in the
  1232. * debug heap
  1233. * int nBlockUse - block type
  1234. *
  1235. *Exit:
  1236. *
  1237. *Exceptions:
  1238. *
  1239. *******************************************************************************/
  1240. _CRTIMP void __cdecl _CrtSetDbgBlockType(
  1241. void * pUserData,
  1242. int nBlockUse
  1243. )
  1244. {
  1245. _CrtMemBlockHeader * pHead;
  1246. #ifdef _MT
  1247. _mlock(_HEAP_LOCK); /* block other threads */
  1248. __try {
  1249. #endif
  1250. /* If from local heap, then change block type. */
  1251. if (_CrtIsValidHeapPointer(pUserData))
  1252. {
  1253. /* get a pointer to memory block header */
  1254. pHead = pHdr(pUserData);
  1255. /* verify block type */
  1256. _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
  1257. pHead->nBlockUse = nBlockUse;
  1258. }
  1259. #ifdef _MT
  1260. }
  1261. __finally {
  1262. _munlock(_HEAP_LOCK); /* release other threads */
  1263. }
  1264. #endif
  1265. return;
  1266. }
  1267. /*---------------------------------------------------------------------------
  1268. *
  1269. * Client-defined allocation hook
  1270. *
  1271. --------------------------------------------------------------------------*/
  1272. /***
  1273. *_CRT_ALLOC_HOOK _CrtSetAllocHook() - set client allocation hook
  1274. *
  1275. *Purpose:
  1276. * set client allocation hook
  1277. *
  1278. *Entry:
  1279. * _CRT_ALLOC_HOOK pfnNewHook - new allocation hook
  1280. *
  1281. *Exit:
  1282. * return previous hook
  1283. *
  1284. *Exceptions:
  1285. *
  1286. *******************************************************************************/
  1287. _CRTIMP _CRT_ALLOC_HOOK __cdecl _CrtSetAllocHook(
  1288. _CRT_ALLOC_HOOK pfnNewHook
  1289. )
  1290. {
  1291. _CRT_ALLOC_HOOK pfnOldHook = _pfnAllocHook;
  1292. _pfnAllocHook = pfnNewHook;
  1293. return pfnOldHook;
  1294. }
  1295. /*---------------------------------------------------------------------------
  1296. *
  1297. * Memory management
  1298. *
  1299. --------------------------------------------------------------------------*/
  1300. /***
  1301. *static int CheckBytes() - verify byte range set to proper value
  1302. *
  1303. *Purpose:
  1304. * verify byte range set to proper value
  1305. *
  1306. *Entry:
  1307. * unsigned char *pb - pointer to start of byte range
  1308. * unsigned char bCheck - value byte range should be set to
  1309. * size_t nSize - size of byte range to be checked
  1310. *
  1311. *Return:
  1312. * TRUE - if all bytes in range equal bcheck
  1313. * FALSE otherwise
  1314. *
  1315. *******************************************************************************/
  1316. static int __cdecl CheckBytes(
  1317. unsigned char * pb,
  1318. unsigned char bCheck,
  1319. size_t nSize
  1320. )
  1321. {
  1322. int bOkay = TRUE;
  1323. while (nSize--)
  1324. {
  1325. if (*pb++ != bCheck)
  1326. {
  1327. /* Internal error report is just noise; calling functions all report results - JWM */
  1328. /* _RPT3(_CRT_WARN, "memory check error at 0x%p = 0x%02X, should be 0x%02X.\n", */
  1329. /* (BYTE *)(pb-1),*(pb-1), bCheck); */
  1330. bOkay = FALSE;
  1331. }
  1332. }
  1333. return bOkay;
  1334. }
  1335. /***
  1336. *int _CrtCheckMemory() - check heap integrity
  1337. *
  1338. *Purpose:
  1339. * Confirm integrity of debug heap. Call _heapchk to validate underlying
  1340. * heap.
  1341. *
  1342. *Entry:
  1343. * void
  1344. *
  1345. *Return:
  1346. * TRUE - if debug and underlying heap appear valid
  1347. * FALSE otherwise
  1348. *
  1349. *******************************************************************************/
  1350. _CRTIMP int __cdecl _CrtCheckMemory(
  1351. void
  1352. )
  1353. {
  1354. int allOkay;
  1355. int nHeapCheck;
  1356. _CrtMemBlockHeader * pHead;
  1357. if (!(_crtDbgFlag & _CRTDBG_ALLOC_MEM_DF))
  1358. return TRUE; /* can't do any checking */
  1359. #ifdef _MT
  1360. _mlock(_HEAP_LOCK); /* block other threads */
  1361. __try {
  1362. #endif
  1363. /* check underlying heap */
  1364. nHeapCheck = _heapchk();
  1365. if (nHeapCheck != _HEAPEMPTY && nHeapCheck != _HEAPOK)
  1366. {
  1367. switch (nHeapCheck)
  1368. {
  1369. case _HEAPBADBEGIN:
  1370. _RPT0(_CRT_WARN, "_heapchk fails with _HEAPBADBEGIN.\n");
  1371. break;
  1372. case _HEAPBADNODE:
  1373. _RPT0(_CRT_WARN, "_heapchk fails with _HEAPBADNODE.\n");
  1374. break;
  1375. case _HEAPEND:
  1376. _RPT0(_CRT_WARN, "_heapchk fails with _HEAPBADEND.\n");
  1377. break;
  1378. case _HEAPBADPTR:
  1379. _RPT0(_CRT_WARN, "_heapchk fails with _HEAPBADPTR.\n");
  1380. break;
  1381. default:
  1382. _RPT0(_CRT_WARN, "_heapchk fails with unknown return value!\n");
  1383. break;
  1384. }
  1385. allOkay = FALSE;
  1386. }
  1387. else
  1388. {
  1389. allOkay = TRUE;
  1390. /* check all allocated blocks */
  1391. for (pHead = _pFirstBlock; pHead != NULL; pHead = pHead->pBlockHeaderNext)
  1392. {
  1393. int okay = TRUE; /* this block okay ? */
  1394. unsigned char * blockUse;
  1395. if (_BLOCK_TYPE_IS_VALID(pHead->nBlockUse))
  1396. blockUse = szBlockUseName[_BLOCK_TYPE(pHead->nBlockUse)];
  1397. else
  1398. blockUse = "DAMAGED";
  1399. /* check no-mans-land gaps */
  1400. if (!CheckBytes(pHead->gap, _bNoMansLandFill, nNoMansLandSize))
  1401. {
  1402. _RPT3(_CRT_WARN, "DAMAGE: before %hs block (#%d) at 0x%p.\n",
  1403. blockUse, pHead->lRequest, (BYTE *) pbData(pHead));
  1404. okay = FALSE;
  1405. }
  1406. if (!CheckBytes(pbData(pHead) + pHead->nDataSize, _bNoMansLandFill,
  1407. nNoMansLandSize))
  1408. {
  1409. _RPT3(_CRT_WARN, "DAMAGE: after %hs block (#%d) at 0x%p.\n",
  1410. blockUse, pHead->lRequest, (BYTE *) pbData(pHead));
  1411. okay = FALSE;
  1412. }
  1413. /* free blocks should remain undisturbed */
  1414. if (pHead->nBlockUse == _FREE_BLOCK &&
  1415. !CheckBytes(pbData(pHead), _bDeadLandFill, pHead->nDataSize))
  1416. {
  1417. _RPT1(_CRT_WARN, "DAMAGE: on top of Free block at 0x%p.\n",
  1418. (BYTE *) pbData(pHead));
  1419. okay = FALSE;
  1420. }
  1421. if (!okay)
  1422. {
  1423. /* report some more statistics about the broken object */
  1424. if (pHead->szFileName != NULL)
  1425. _RPT3(_CRT_WARN, "%hs allocated at file %hs(%d).\n",
  1426. blockUse, pHead->szFileName, pHead->nLine);
  1427. _RPT3(_CRT_WARN, "%hs located at 0x%p is %Iu bytes long.\n",
  1428. blockUse, (BYTE *)pbData(pHead), pHead->nDataSize);
  1429. allOkay = FALSE;
  1430. }
  1431. }
  1432. }
  1433. #ifdef _MT
  1434. }
  1435. __finally {
  1436. _munlock( _HEAP_LOCK ); /* release other threads */
  1437. }
  1438. #endif
  1439. return allOkay;
  1440. }
  1441. /***
  1442. *int _CrtSetDbgFlag() - get/set the _crtDbgFlag
  1443. *
  1444. *Purpose:
  1445. * get or set the _crtDbgFlag
  1446. *
  1447. *Entry:
  1448. * int bNewBits - new Flag or _CRTDBG_REPORT_FLAG
  1449. *
  1450. *Return:
  1451. * previous flag state
  1452. *
  1453. *******************************************************************************/
  1454. _CRTIMP int __cdecl _CrtSetDbgFlag(
  1455. int fNewBits
  1456. )
  1457. {
  1458. int fOldBits;
  1459. #ifdef _MT
  1460. _mlock(_HEAP_LOCK); /* block other threads */
  1461. __try {
  1462. #endif
  1463. fOldBits = _crtDbgFlag;
  1464. if ( fNewBits != _CRTDBG_REPORT_FLAG )
  1465. {
  1466. if ( fNewBits & _CRTDBG_CHECK_ALWAYS_DF )
  1467. check_frequency = 1;
  1468. else
  1469. check_frequency = (fNewBits >> 16) & 0x0ffff;
  1470. check_counter = 0;
  1471. _crtDbgFlag = fNewBits;
  1472. }
  1473. #ifdef _MT
  1474. }
  1475. __finally {
  1476. _munlock( _HEAP_LOCK );
  1477. }
  1478. #endif
  1479. return fOldBits;
  1480. }
  1481. /***
  1482. *int _CrtDoForAllClientObjects() - call a client-supplied function for all
  1483. * client objects in the heap
  1484. *
  1485. *Purpose:
  1486. * call a client-supplied function for all client objects in the heap
  1487. *
  1488. *Entry:
  1489. * void (*pfn)(void *, void *) - pointer to client function to call
  1490. * void * pContext - pointer to user supplied context to pass to function
  1491. *
  1492. *Return:
  1493. * void
  1494. *
  1495. *******************************************************************************/
  1496. _CRTIMP void __cdecl _CrtDoForAllClientObjects(
  1497. void (*pfn)(void *, void *),
  1498. void * pContext
  1499. )
  1500. {
  1501. _CrtMemBlockHeader * pHead;
  1502. if (!(_crtDbgFlag & _CRTDBG_ALLOC_MEM_DF))
  1503. return; /* sorry not enabled */
  1504. #ifdef _MT
  1505. _mlock(_HEAP_LOCK); /* block other threads */
  1506. __try {
  1507. #endif
  1508. for (pHead = _pFirstBlock; pHead != NULL; pHead = pHead->pBlockHeaderNext)
  1509. {
  1510. if (_BLOCK_TYPE(pHead->nBlockUse) == _CLIENT_BLOCK)
  1511. (*pfn)((void *) pbData(pHead), pContext);
  1512. }
  1513. #ifdef _MT
  1514. }
  1515. __finally {
  1516. _munlock(_HEAP_LOCK); /* release other threads */
  1517. }
  1518. #endif
  1519. }
  1520. /***
  1521. *int _CrtIsValidPointer() - verify memory range is valid for reading/writing
  1522. *
  1523. *Purpose:
  1524. * verify memory range range is valid for reading/writing
  1525. *
  1526. *Entry:
  1527. * const void * pv - start of memory range to test
  1528. * unsigned int nBytes - size of memory range
  1529. * int bReadWrite - TRUE if read/write, FALSE if read-only
  1530. *
  1531. *Return:
  1532. * TRUE - if valid address
  1533. * FALSE otherwise
  1534. *
  1535. *******************************************************************************/
  1536. _CRTIMP int __cdecl _CrtIsValidPointer(
  1537. const void * pv,
  1538. unsigned int nBytes,
  1539. int bReadWrite
  1540. )
  1541. {
  1542. return (
  1543. pv != NULL &&
  1544. !IsBadReadPtr(pv, nBytes) &&
  1545. (!bReadWrite || !IsBadWritePtr((LPVOID)pv, nBytes))
  1546. );
  1547. }
  1548. /***
  1549. *int _CrtIsValidHeapPointer() - verify pointer is from 'local' heap
  1550. *
  1551. *Purpose:
  1552. * Verify pointer is not only a valid pointer but also that it is from
  1553. * the 'local' heap. Pointers from another copy of the C runtime (even in the
  1554. * same process) will be caught.
  1555. *
  1556. *Entry:
  1557. * const void * pUserData - pointer of interest
  1558. *
  1559. *Return:
  1560. * TRUE - if valid and from local heap
  1561. * FALSE otherwise
  1562. *
  1563. *******************************************************************************/
  1564. _CRTIMP int __cdecl _CrtIsValidHeapPointer(
  1565. const void * pUserData
  1566. )
  1567. {
  1568. if (!pUserData)
  1569. return FALSE;
  1570. if (!_CrtIsValidPointer(pHdr(pUserData), sizeof(_CrtMemBlockHeader), FALSE))
  1571. return FALSE;
  1572. #ifndef _WIN64
  1573. if ( __active_heap == __V6_HEAP )
  1574. {
  1575. PHEADER pHeader;
  1576. if (pHeader = __sbh_find_block(pHdr(pUserData)))
  1577. {
  1578. return __sbh_verify_block(pHeader, pHdr(pUserData));
  1579. }
  1580. else if ( (_osver & 0x8000) != 0 )
  1581. return TRUE;
  1582. else
  1583. return HeapValidate( _crtheap, 0, pHdr(pUserData) );
  1584. }
  1585. #ifdef CRTDLL
  1586. else if ( __active_heap == __V5_HEAP )
  1587. {
  1588. __old_sbh_region_t * preg;
  1589. __old_sbh_page_t * ppage;
  1590. __old_page_map_t * pmap;
  1591. if ( (pmap = __old_sbh_find_block( pHdr(pUserData), &preg, &ppage )) !=
  1592. NULL )
  1593. {
  1594. if ( *pmap )
  1595. return TRUE;
  1596. else
  1597. return FALSE;
  1598. }
  1599. else if ( (_osver & 0x8000) != 0 )
  1600. return TRUE;
  1601. else
  1602. return HeapValidate( _crtheap, 0, pHdr(pUserData) );
  1603. }
  1604. #endif /* CRTDLL */
  1605. else // __active_heap == _SYSTEM_HEAP
  1606. #endif /* ndef _WIN64 */
  1607. {
  1608. return HeapValidate( _crtheap, 0, pHdr(pUserData) );
  1609. }
  1610. }
  1611. /***
  1612. *int _CrtIsMemoryBlock() - verify memory block is debug heap block
  1613. *
  1614. *Purpose:
  1615. * verify memory block is debug heap block
  1616. *
  1617. *Entry:
  1618. * const void * pUserData - start of memory block
  1619. * unsigned int nBytes - size of memory block
  1620. * long * plRequestNumber - if !NULL, set to request number
  1621. * char ** pszFileName - if !NULL, set to file name
  1622. * int * pnLine - if !NULL, set to line number
  1623. *
  1624. *Return:
  1625. * TRUE - if debug memory heap address
  1626. * FALSE otherwise
  1627. *
  1628. *******************************************************************************/
  1629. _CRTIMP int __cdecl _CrtIsMemoryBlock(
  1630. const void * pUserData,
  1631. unsigned int nBytes,
  1632. long * plRequestNumber,
  1633. char ** pszFileName,
  1634. int * pnLine
  1635. )
  1636. {
  1637. _CrtMemBlockHeader * pHead;
  1638. int retval;
  1639. if (!_CrtIsValidHeapPointer(pUserData))
  1640. return FALSE;
  1641. #ifdef _MT
  1642. _mlock(_HEAP_LOCK); /* block other threads */
  1643. __try {
  1644. #endif
  1645. pHead = pHdr(pUserData);
  1646. if (_BLOCK_TYPE_IS_VALID(pHead->nBlockUse) &&
  1647. _CrtIsValidPointer(pUserData, nBytes, TRUE) &&
  1648. pHead->nDataSize == nBytes &&
  1649. pHead->lRequest <= _lRequestCurr
  1650. )
  1651. {
  1652. if (plRequestNumber != NULL)
  1653. *plRequestNumber = pHead->lRequest;
  1654. if (pszFileName != NULL)
  1655. *pszFileName = pHead->szFileName;
  1656. if (pnLine != NULL)
  1657. *pnLine = pHead->nLine;
  1658. retval = TRUE;
  1659. }
  1660. else
  1661. retval = FALSE;
  1662. #ifdef _MT
  1663. }
  1664. __finally {
  1665. _munlock(_HEAP_LOCK); /* release other threads */
  1666. }
  1667. #endif
  1668. return retval;
  1669. }
  1670. /***
  1671. *
  1672. *Purpose:
  1673. * return memory block type for a debug heap block
  1674. *
  1675. *Entry:
  1676. * const void * pUserData - start of memory block
  1677. *
  1678. *Return:
  1679. * Block type if pUserData is a valid debug heap block pointer, else -1.
  1680. *
  1681. *******************************************************************************/
  1682. _CRTIMP int _CrtReportBlockType(
  1683. const void * pUserData
  1684. )
  1685. {
  1686. _CrtMemBlockHeader * pHead;
  1687. if (!_CrtIsValidHeapPointer(pUserData))
  1688. return -1;
  1689. pHead = pHdr(pUserData);
  1690. return pHead->nBlockUse;
  1691. }
  1692. /*---------------------------------------------------------------------------
  1693. *
  1694. * Memory state
  1695. *
  1696. --------------------------------------------------------------------------*/
  1697. /***
  1698. *_CRT_DUMP_CLIENT _CrtSetDumpClient() - set client dump routine
  1699. *
  1700. *Purpose:
  1701. * set client dump routine
  1702. *
  1703. *Entry:
  1704. * _CRT_DUMP_CLIENT pfnNewDumpClient - new dump routine
  1705. *
  1706. *Exit:
  1707. * return previous dump routine
  1708. *
  1709. *Exceptions:
  1710. *
  1711. *******************************************************************************/
  1712. _CRTIMP _CRT_DUMP_CLIENT __cdecl _CrtSetDumpClient(
  1713. _CRT_DUMP_CLIENT pfnNewDump
  1714. )
  1715. {
  1716. _CRT_DUMP_CLIENT pfnOldDump = _pfnDumpClient;
  1717. _pfnDumpClient = pfnNewDump;
  1718. return pfnOldDump;
  1719. }
  1720. /***
  1721. *_CrtMemState * _CrtMemStateCheckpoint() - checkpoint current memory state
  1722. *
  1723. *Purpose:
  1724. * checkpoint current memory state
  1725. *
  1726. *Entry:
  1727. * _CrtMemState * state - state structure to fill in, will be
  1728. * allocated if NULL
  1729. *
  1730. *Return:
  1731. * current memory state
  1732. *
  1733. *******************************************************************************/
  1734. _CRTIMP void __cdecl _CrtMemCheckpoint(
  1735. _CrtMemState * state
  1736. )
  1737. {
  1738. int use;
  1739. _CrtMemBlockHeader * pHead;
  1740. if (state == NULL)
  1741. {
  1742. _RPT0(_CRT_WARN, "_CrtMemCheckPoint: NULL state pointer.\n");
  1743. return;
  1744. }
  1745. #ifdef _MT
  1746. _mlock(_HEAP_LOCK); /* block other threads */
  1747. __try {
  1748. #endif
  1749. state->pBlockHeader = _pFirstBlock;
  1750. for (use = 0; use < _MAX_BLOCKS; use++)
  1751. state->lCounts[use] = state->lSizes[use] = 0;
  1752. for (pHead = _pFirstBlock; pHead != NULL; pHead = pHead->pBlockHeaderNext)
  1753. {
  1754. if (_BLOCK_TYPE(pHead->nBlockUse) >= 0 && _BLOCK_TYPE(pHead->nBlockUse) < _MAX_BLOCKS)
  1755. {
  1756. state->lCounts[_BLOCK_TYPE(pHead->nBlockUse)]++;
  1757. state->lSizes[_BLOCK_TYPE(pHead->nBlockUse)] += pHead->nDataSize;
  1758. }
  1759. else
  1760. {
  1761. _RPT1(_CRT_WARN, "Bad memory block found at 0x%p.\n", (BYTE *)pHead);
  1762. }
  1763. }
  1764. state->lHighWaterCount = _lMaxAlloc;
  1765. state->lTotalCount = _lTotalAlloc;
  1766. #ifdef _MT
  1767. }
  1768. __finally {
  1769. _munlock(_HEAP_LOCK); /* release other threads */
  1770. }
  1771. #endif
  1772. }
  1773. /***
  1774. *int _CrtMemDifference() - compare two memory states
  1775. *
  1776. *Purpose:
  1777. * compare two memory states
  1778. *
  1779. *Entry:
  1780. * _CrtMemState * state - return memory state difference
  1781. * _CrtMemState * oldState - earlier memory state
  1782. * _CrtMemState * newState - later memory state
  1783. *
  1784. *Return:
  1785. * TRUE if difference
  1786. * FALSE otherwise
  1787. *
  1788. *******************************************************************************/
  1789. _CRTIMP int __cdecl _CrtMemDifference(
  1790. _CrtMemState * state,
  1791. const _CrtMemState * oldState,
  1792. const _CrtMemState * newState
  1793. )
  1794. {
  1795. int use;
  1796. int bSignificantDifference = FALSE;
  1797. if (state == NULL || oldState == NULL || newState == NULL)
  1798. {
  1799. _RPT0(_CRT_WARN, "_CrtMemDifference: NULL state pointer.\n");
  1800. return bSignificantDifference;
  1801. }
  1802. for (use = 0; use < _MAX_BLOCKS; use++)
  1803. {
  1804. state->lSizes[use] = newState->lSizes[use] - oldState->lSizes[use];
  1805. state->lCounts[use] = newState->lCounts[use] - oldState->lCounts[use];
  1806. if ( (state->lSizes[use] != 0 || state->lCounts[use] != 0) &&
  1807. use != _FREE_BLOCK &&
  1808. (use != _CRT_BLOCK ||
  1809. (use == _CRT_BLOCK && (_crtDbgFlag & _CRTDBG_CHECK_CRT_DF)))
  1810. )
  1811. bSignificantDifference = TRUE;
  1812. }
  1813. state->lHighWaterCount = newState->lHighWaterCount - oldState->lHighWaterCount;
  1814. state->lTotalCount = newState->lTotalCount - oldState->lTotalCount;
  1815. state->pBlockHeader = NULL;
  1816. return bSignificantDifference;
  1817. }
  1818. #define MAXPRINT 16
  1819. static void __cdecl _printMemBlockData(
  1820. _CrtMemBlockHeader * pHead
  1821. )
  1822. {
  1823. int i;
  1824. unsigned char ch;
  1825. unsigned char printbuff[MAXPRINT+1];
  1826. unsigned char valbuff[MAXPRINT*3+1];
  1827. for (i = 0; i < min((int)pHead->nDataSize, MAXPRINT); i++)
  1828. {
  1829. ch = pbData(pHead)[i];
  1830. printbuff[i] = isprint(ch) ? ch : ' ';
  1831. sprintf(&valbuff[i*3], "%.2X ", ch);
  1832. }
  1833. printbuff[i] = '\0';
  1834. _RPT2(_CRT_WARN, " Data: <%s> %s\n", printbuff, valbuff);
  1835. }
  1836. /***
  1837. *void _CrtMemDumpAllObjectsSince() - dump all objects since memory state
  1838. *
  1839. *Purpose:
  1840. * dump all objects since memory state
  1841. *
  1842. *Entry:
  1843. * _CrtMemState * state - dump since this state
  1844. *
  1845. *Return:
  1846. * void
  1847. *
  1848. *******************************************************************************/
  1849. _CRTIMP void __cdecl _CrtMemDumpAllObjectsSince(
  1850. const _CrtMemState * state
  1851. )
  1852. {
  1853. _CrtMemBlockHeader * pHead;
  1854. _CrtMemBlockHeader * pStopBlock = NULL;
  1855. #ifdef _MT
  1856. _mlock(_HEAP_LOCK); /* block other threads */
  1857. __try {
  1858. #endif
  1859. _RPT0(_CRT_WARN, "Dumping objects ->\n");
  1860. if (state)
  1861. pStopBlock = state->pBlockHeader;
  1862. for (pHead = _pFirstBlock; pHead != NULL && pHead != pStopBlock;
  1863. pHead = pHead->pBlockHeaderNext)
  1864. {
  1865. if (_BLOCK_TYPE(pHead->nBlockUse) == _IGNORE_BLOCK ||
  1866. _BLOCK_TYPE(pHead->nBlockUse) == _FREE_BLOCK ||
  1867. (_BLOCK_TYPE(pHead->nBlockUse) == _CRT_BLOCK &&
  1868. !(_crtDbgFlag & _CRTDBG_CHECK_CRT_DF))
  1869. )
  1870. {
  1871. /* ignore it for dumping */
  1872. }
  1873. else {
  1874. if (pHead->szFileName != NULL)
  1875. {
  1876. if (!_CrtIsValidPointer(pHead->szFileName, 1, FALSE))
  1877. _RPT1(_CRT_WARN, "#File Error#(%d) : ", pHead->nLine);
  1878. else
  1879. _RPT2(_CRT_WARN, "%hs(%d) : ", pHead->szFileName, pHead->nLine);
  1880. }
  1881. _RPT1(_CRT_WARN, "{%ld} ", pHead->lRequest);
  1882. if (_BLOCK_TYPE(pHead->nBlockUse) == _CLIENT_BLOCK)
  1883. {
  1884. _RPT3(_CRT_WARN, "client block at 0x%p, subtype %x, %Iu bytes long.\n",
  1885. (BYTE *)pbData(pHead), _BLOCK_SUBTYPE(pHead->nBlockUse), pHead->nDataSize);
  1886. if (_pfnDumpClient)
  1887. (*_pfnDumpClient)( (void *) pbData(pHead), pHead->nDataSize);
  1888. else
  1889. _printMemBlockData(pHead);
  1890. }
  1891. else if (pHead->nBlockUse == _NORMAL_BLOCK)
  1892. {
  1893. _RPT2(_CRT_WARN, "normal block at 0x%p, %Iu bytes long.\n",
  1894. (BYTE *)pbData(pHead), pHead->nDataSize);
  1895. _printMemBlockData(pHead);
  1896. }
  1897. else if (_BLOCK_TYPE(pHead->nBlockUse) == _CRT_BLOCK)
  1898. {
  1899. _RPT3(_CRT_WARN, "crt block at 0x%p, subtype %x, %Iu bytes long.\n",
  1900. (BYTE *)pbData(pHead), _BLOCK_SUBTYPE(pHead->nBlockUse), pHead->nDataSize);
  1901. _printMemBlockData(pHead);
  1902. }
  1903. }
  1904. }
  1905. #ifdef _MT
  1906. }
  1907. __finally {
  1908. _munlock(_HEAP_LOCK); /* release other threads */
  1909. }
  1910. #endif
  1911. _RPT0(_CRT_WARN, "Object dump complete.\n");
  1912. }
  1913. /***
  1914. *void _CrtMemDumpMemoryLeaks() - dump all objects still in heap
  1915. *
  1916. *Purpose:
  1917. * dump all objects still in heap. used to detect memory leaks over the
  1918. * life of a program
  1919. *
  1920. *Entry:
  1921. * void
  1922. *
  1923. *Return:
  1924. * TRUE if memory leaks
  1925. * FALSE otherwise
  1926. *
  1927. *******************************************************************************/
  1928. _CRTIMP int __cdecl _CrtDumpMemoryLeaks(
  1929. void
  1930. )
  1931. {
  1932. /* only dump leaks when there are in fact leaks */
  1933. _CrtMemState msNow;
  1934. _CrtMemCheckpoint(&msNow);
  1935. if (msNow.lCounts[_CLIENT_BLOCK] != 0 ||
  1936. msNow.lCounts[_NORMAL_BLOCK] != 0 ||
  1937. (_crtDbgFlag & _CRTDBG_CHECK_CRT_DF &&
  1938. msNow.lCounts[_CRT_BLOCK] != 0)
  1939. )
  1940. {
  1941. /* difference detected: dump objects since start. */
  1942. _RPT0(_CRT_WARN, "Detected memory leaks!\n");
  1943. _CrtMemDumpAllObjectsSince(NULL);
  1944. return TRUE;
  1945. }
  1946. return FALSE; /* no leaked objects */
  1947. }
  1948. /***
  1949. *_CrtMemState * _CrtMemDumpStatistics() - dump memory state
  1950. *
  1951. *Purpose:
  1952. * dump memory state
  1953. *
  1954. *Entry:
  1955. * _CrtMemState * state - dump this state
  1956. *
  1957. *Return:
  1958. * void
  1959. *
  1960. *******************************************************************************/
  1961. _CRTIMP void __cdecl _CrtMemDumpStatistics(
  1962. const _CrtMemState * state
  1963. )
  1964. {
  1965. int use;
  1966. if (state == NULL)
  1967. return;
  1968. for (use = 0; use < _MAX_BLOCKS; use++)
  1969. {
  1970. _RPT3(_CRT_WARN, "%Id bytes in %Id %hs Blocks.\n",
  1971. state->lSizes[use], state->lCounts[use], szBlockUseName[use]);
  1972. }
  1973. _RPT1(_CRT_WARN, "Largest number used: %Id bytes.\n", state->lHighWaterCount);
  1974. _RPT1(_CRT_WARN, "Total allocations: %Id bytes.\n", state->lTotalCount);
  1975. }
  1976. /***
  1977. * void *_aligned_malloc(size_t size, size_t alignment)
  1978. * - Get a block of aligned memory from the heap.
  1979. *
  1980. * Purpose:
  1981. * Allocate of block of aligned memory aligned on the alignment of at least
  1982. * size bytes from the heap and return a pointer to it.
  1983. *
  1984. * Entry:
  1985. * size_t size - size of block requested
  1986. * size_t alignment - alignment of memory
  1987. *
  1988. * Exit:
  1989. * Sucess: Pointer to memory block
  1990. * Faliure: Null
  1991. *******************************************************************************/
  1992. _CRTIMP void * __cdecl _aligned_malloc(
  1993. size_t size,
  1994. size_t align
  1995. )
  1996. {
  1997. return _aligned_offset_malloc_dbg(size, align, 0, NULL, 0);
  1998. }
  1999. /***
  2000. * void *_aligned_malloc_dbg(size_t size, size_t alignment,
  2001. * const char *f_name, int line_n)
  2002. * - Get a block of aligned memory from the heap.
  2003. *
  2004. * Purpose:
  2005. * Allocate of block of aligned memory aligned on the alignment of at least
  2006. * size bytes from the heap and return a pointer to it.
  2007. *
  2008. * Entry:
  2009. * size_t size - size of block requested
  2010. * size_t alignment - alignment of memory
  2011. * const char * f_name - file name
  2012. * int line_n - line number
  2013. *
  2014. * Exit:
  2015. * Sucess: Pointer to memory block
  2016. * Faliure: Null
  2017. *
  2018. *******************************************************************************/
  2019. _CRTIMP void * __cdecl _aligned_malloc_dbg(
  2020. size_t size,
  2021. size_t align,
  2022. const char * f_name,
  2023. int line_n
  2024. )
  2025. {
  2026. return _aligned_offset_malloc_dbg(size, align, 0, f_name, line_n);
  2027. }
  2028. /***
  2029. *
  2030. * void *_aligned_realloc(size_t size, size_t alignment)
  2031. * - Reallocate a block of aligned memory from the heap.
  2032. *
  2033. * Purpose:
  2034. * Reallocates of block of aligned memory aligned on the alignment of at
  2035. * least size bytes from the heap and return a pointer to it. Size can be
  2036. * either greater or less than the original size of the block.
  2037. * The reallocation may result in moving the block as well as changing the
  2038. * size.
  2039. *
  2040. * Entry:
  2041. * void *memblock - pointer to block in the heap previously allocated by
  2042. * call to _aligned_malloc(), _aligned_offset_malloc(),
  2043. * _aligned_realloc() or _aligned_offset_realloc().
  2044. * size_t size - size of block requested
  2045. * size_t alignment - alignment of memory
  2046. *
  2047. * Exit:
  2048. * Sucess: Pointer to re-allocated memory block
  2049. * Faliure: Null
  2050. *
  2051. *******************************************************************************/
  2052. _CRTIMP void * __cdecl _aligned_realloc(
  2053. void * memblock,
  2054. size_t size,
  2055. size_t align
  2056. )
  2057. {
  2058. return _aligned_offset_realloc_dbg(memblock, size, align, 0, NULL, 0);
  2059. }
  2060. /***
  2061. *
  2062. * void *_aligned_realloc_dbg(void * memblock, size_t size, size_t alignment,
  2063. * const char * f_name, int line_n)
  2064. * - Reallocate a block of aligned memory from the heap.
  2065. *
  2066. * Purpose:
  2067. * Reallocates of block of aligned memory aligned on the alignment of at
  2068. * least size bytes from the heap and return a pointer to it. Size can be
  2069. * either greater or less than the original size of the block.
  2070. * The reallocation may result in moving the block as well as changing the
  2071. * size.
  2072. *
  2073. * Entry:
  2074. * void *memblock - pointer to block in the heap previously allocated by
  2075. * call to _aligned_malloc(), _aligned_offset_malloc(),
  2076. * _aligned_realloc() or _aligned_offset_realloc().
  2077. * size_t size - size of block requested
  2078. * size_t alignment - alignment of memory
  2079. * const char * f_name - file name
  2080. * int - line number
  2081. *
  2082. * Exit:
  2083. * Sucess: Pointer to re-allocated memory block
  2084. * Faliure: Null
  2085. *
  2086. *******************************************************************************/
  2087. _CRTIMP void * __cdecl _aligned_realloc_dbg(
  2088. void *memblock,
  2089. size_t size,
  2090. size_t align,
  2091. const char * f_name,
  2092. int line_n
  2093. )
  2094. {
  2095. return _aligned_offset_realloc_dbg(memblock, size, align, 0, f_name, line_n);
  2096. }
  2097. /***
  2098. *
  2099. * void *_aligned_offset_malloc(size_t size, size_t alignment, int offset)
  2100. * - Allocates a block of memory from the heap.
  2101. *
  2102. * Purpose:
  2103. * Reallocates a block of memory which is shifted by offset from
  2104. * alignment of at least size bytes from the heap and return a pointer
  2105. * to it. Size can be either greater or less than the original size of the
  2106. * block.
  2107. *
  2108. * Entry:
  2109. * size_t size - size of block of memory
  2110. * size_t alignment - alignment of memory
  2111. * size_t offset - offset of memory from the alignment
  2112. *
  2113. * Exit:
  2114. * Sucess: Pointer to the re-allocated memory block
  2115. * Faliure: Null
  2116. *
  2117. *******************************************************************************/
  2118. _CRTIMP void * __cdecl _aligned_offset_malloc(
  2119. size_t size,
  2120. size_t align,
  2121. size_t offset
  2122. )
  2123. {
  2124. return _aligned_offset_malloc_dbg(size, align, offset, NULL, 0);
  2125. }
  2126. /***
  2127. *
  2128. * void *_aligned_offset_malloc_dbg(size_t size, size_t alignment, int offset,
  2129. * const char * f_name, int line_n)
  2130. *
  2131. * Purpose:
  2132. * Reallocates a block of memory which is shifted by offset from
  2133. * alignment of at least size bytes from the heap and return a pointer
  2134. * to it. Size can be either greater or less than the original size of the
  2135. * block.
  2136. *
  2137. * Entry:
  2138. * size_t size - size of block of memory
  2139. * size_t alignment - alignment of memory
  2140. * size_t offset - offset of memory from the alignment
  2141. * const char * f_name - file name
  2142. * int line_n - line number
  2143. *
  2144. * Exit:
  2145. * Sucess: Pointer to the re-allocated memory block
  2146. * Faliure: Null
  2147. *
  2148. *******************************************************************************/
  2149. _CRTIMP void * __cdecl _aligned_offset_malloc_dbg(
  2150. size_t size,
  2151. size_t align,
  2152. size_t offset,
  2153. const char * f_name,
  2154. int line_n
  2155. )
  2156. {
  2157. uintptr_t ptr, r_ptr, t_ptr;
  2158. _AlignMemBlockHdr *pHdr;
  2159. if (!IS_2_POW_N(align))
  2160. {
  2161. _ASSERTE(("alignment must be a power of 2",0));
  2162. errno = EINVAL;
  2163. return NULL;
  2164. }
  2165. if ( offset >= size && offset != 0)
  2166. {
  2167. _ASSERTE(("offset must be within size", 0));
  2168. errno = EINVAL;
  2169. return NULL;
  2170. }
  2171. align = (align > sizeof(uintptr_t) ? align : sizeof(uintptr_t)) -1;
  2172. t_ptr = (0 -offset)&(sizeof(uintptr_t) -1);
  2173. if ((ptr = (uintptr_t) _malloc_dbg(t_ptr + size + align + sizeof(_AlignMemBlockHdr), _NORMAL_BLOCK, f_name, line_n)) == (uintptr_t)NULL)
  2174. return NULL;
  2175. r_ptr =((ptr +align +t_ptr +sizeof(_AlignMemBlockHdr) +offset)&~align)-offset;
  2176. pHdr = (_AlignMemBlockHdr *)(r_ptr - t_ptr) -1;
  2177. memset((void *)pHdr->Gap, _bAlignLandFill, nNoMansLandSize);
  2178. pHdr->pHead = (void *)ptr;
  2179. return (void *) r_ptr;
  2180. }
  2181. /***
  2182. *
  2183. * void *_aligned_offset_realloc(size_t size, size_t alignment, int offset)
  2184. * - Reallocate a block of memory from the heap.
  2185. *
  2186. * Purpose:
  2187. * Reallocates a block of memory which is shifted by offset from
  2188. * alignment of at least size bytes from the heap and return a pointer
  2189. * to it. Size can be either greater or less than the original size of the
  2190. * block.
  2191. *
  2192. * Entry:
  2193. * void *memblock - pointer to block in the heap previously allocated by
  2194. * call to _aligned_malloc(), _aligned_offset_malloc(),
  2195. * _aligned_realloc() or _aligned_offset_realloc().
  2196. * size_t size - size of block of memory
  2197. * size_t alignment - alignment of memory
  2198. * size_t offset - offset of memory from the alignment
  2199. *
  2200. * Exit:
  2201. * Sucess: Pointer to the re-allocated memory block
  2202. * Faliure: Null
  2203. *
  2204. *******************************************************************************/
  2205. _CRTIMP void * __cdecl _aligned_offset_realloc(
  2206. void * memblock,
  2207. size_t size,
  2208. size_t align,
  2209. size_t offset
  2210. )
  2211. {
  2212. return _aligned_offset_realloc_dbg(memblock, size, align, offset, NULL, 0);
  2213. }
  2214. /***
  2215. *
  2216. * void *_aligned_offset_realloc_dbg(void *memblock, size_t size,
  2217. * size_t alignment, int offset,
  2218. * const char * f_name, int line_n)
  2219. * - Reallocate a block of memory from the heap.
  2220. *
  2221. * Purpose:
  2222. * Reallocates a block of memory which is shifted by offset from
  2223. * alignment of at least size bytes from the heap and return a pointer
  2224. * to it. Size can be either greater or less than the original size of the
  2225. * block.
  2226. *
  2227. * Entry:
  2228. * void *memblock - pointer to block in the heap previously allocated by
  2229. * call to _aligned_malloc(), _aligned_offset_malloc(),
  2230. * _aligned_realloc() or _aligned_offset_realloc().
  2231. * size_t size - size of block of memory
  2232. * size_t alignment - alignment of memory
  2233. * size_t offset - offset of memory from the alignment
  2234. * const char * f_name - file name
  2235. * int line_n - line number
  2236. *
  2237. * Exit:
  2238. * Sucess: Pointer to the re-allocated memory block
  2239. * Faliure: Null
  2240. *
  2241. *
  2242. *******************************************************************************/
  2243. _CRTIMP void * __cdecl _aligned_offset_realloc_dbg(
  2244. void * memblock,
  2245. size_t size,
  2246. size_t align,
  2247. size_t offset,
  2248. const char * f_name,
  2249. int line_n
  2250. )
  2251. {
  2252. uintptr_t ptr, r_ptr, t_ptr, mov_sz;
  2253. _AlignMemBlockHdr *pHdr, *s_pHdr;
  2254. if ( memblock == NULL)
  2255. {
  2256. return _aligned_offset_malloc_dbg(size, align, offset, f_name, line_n);
  2257. }
  2258. if ( size == 0)
  2259. {
  2260. _aligned_free_dbg(memblock);
  2261. return NULL;
  2262. }
  2263. s_pHdr = (_AlignMemBlockHdr *)((uintptr_t)memblock & ~(sizeof(uintptr_t) -1)) -1;
  2264. if ( CheckBytes((unsigned char *)memblock -nNoMansLandSize, _bNoMansLandFill, nNoMansLandSize))
  2265. {
  2266. _RPT1(_CRT_ERROR, "The block at 0x%p was not allocated by _aligned routines, use realloc()", memblock);
  2267. return NULL;
  2268. }
  2269. if(!CheckBytes(s_pHdr->Gap, _bAlignLandFill, nNoMansLandSize))
  2270. {
  2271. _RPT1(_CRT_ERROR, "Damage before 0x%p which was allocated by aligned routine\n", memblock);
  2272. }
  2273. if (!IS_2_POW_N(align))
  2274. {
  2275. _ASSERTE(("alignment must be a power of 2",0));
  2276. errno = EINVAL;
  2277. return NULL;
  2278. }
  2279. if ( offset >= size && offset != 0)
  2280. {
  2281. _ASSERTE(("offset must be within size", 0));
  2282. errno = EINVAL;
  2283. return NULL;
  2284. }
  2285. mov_sz = _msize(s_pHdr->pHead) - ((uintptr_t)memblock - (uintptr_t)s_pHdr->pHead);
  2286. align = (align > sizeof(uintptr_t) ? align : sizeof(uintptr_t)) -1;
  2287. t_ptr = (0 -offset)&(sizeof(uintptr_t) -1);
  2288. if ((ptr = (uintptr_t) _malloc_dbg(t_ptr + size + align + sizeof(_AlignMemBlockHdr), _NORMAL_BLOCK, f_name, line_n)) == (uintptr_t)NULL)
  2289. return NULL;
  2290. r_ptr =((ptr +align +t_ptr +sizeof(_AlignMemBlockHdr) +offset)&~align)-offset;
  2291. pHdr = (_AlignMemBlockHdr *)(r_ptr - t_ptr) -1;
  2292. memset((void *)pHdr->Gap, _bAlignLandFill, nNoMansLandSize);
  2293. pHdr->pHead = (void *)ptr;
  2294. memcpy((void *)r_ptr, memblock, mov_sz > size ? size : mov_sz);
  2295. _free_dbg(s_pHdr->pHead, _NORMAL_BLOCK);
  2296. return (void *) r_ptr;
  2297. }
  2298. /***
  2299. *
  2300. * void *_aligned_free(void *memblock)
  2301. * - Free the memory which was allocated using _aligned_malloc or
  2302. * _aligned_offset_memory
  2303. *
  2304. * Purpose:
  2305. * Frees the algned memory block which was allocated using _aligned_malloc
  2306. * or _aligned_memory.
  2307. *
  2308. * Entry:
  2309. * void * memblock - pointer to the block of memory
  2310. *
  2311. *******************************************************************************/
  2312. _CRTIMP void __cdecl _aligned_free(
  2313. void *memblock
  2314. )
  2315. {
  2316. _aligned_free_dbg(memblock);
  2317. }
  2318. /***
  2319. *
  2320. * void *_aligned_free_dbg(void *memblock, const char * file_n, int line_n)
  2321. * - Free the memory which was allocated using _aligned_malloc or
  2322. * _aligned_offset_memory
  2323. *
  2324. * Purpose:
  2325. * Frees the algned memory block which was allocated using _aligned_malloc
  2326. * or _aligned_memory.
  2327. *
  2328. * Entry:
  2329. * void * memblock - pointer to the block of memory
  2330. *
  2331. *******************************************************************************/
  2332. _CRTIMP void __cdecl _aligned_free_dbg(
  2333. void * memblock
  2334. )
  2335. {
  2336. _AlignMemBlockHdr *pHdr;
  2337. if ( memblock == NULL)
  2338. return;
  2339. pHdr = (_AlignMemBlockHdr *)((uintptr_t)memblock & ~(sizeof(uintptr_t) -1)) -1;
  2340. if ( CheckBytes((unsigned char *)memblock -nNoMansLandSize, _bNoMansLandFill, nNoMansLandSize))
  2341. {
  2342. _RPT1(_CRT_ERROR, "The block at 0x%p was not allocated by _aligned routines, use free()", memblock);
  2343. return;
  2344. }
  2345. if(!CheckBytes(pHdr->Gap, _bAlignLandFill, nNoMansLandSize))
  2346. {
  2347. _RPT1(_CRT_ERROR, "Damage before 0x%p which was allocated by aligned routine\n", memblock);
  2348. }
  2349. _free_dbg((void *)pHdr->pHead, _NORMAL_BLOCK);
  2350. }
  2351. #endif /* _DEBUG */