Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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