home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / heapchk.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  7KB  |  349 lines

  1. /***
  2. *heapchk.c - perform a consistency check on the heap
  3. *
  4. *       Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       Defines the _heapchk() and _heapset() functions
  8. *
  9. *******************************************************************************/
  10.  
  11.  
  12. #ifdef WINHEAP
  13.  
  14.  
  15. #include <cruntime.h>
  16. #include <windows.h>
  17. #include <errno.h>
  18. #include <malloc.h>
  19. #include <mtdll.h>
  20. #include <stddef.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <winheap.h>
  24.  
  25.  
  26. /***
  27. *int _heapchk()         - Validate the heap
  28. *int _heapset(_fill)    - Obsolete function!
  29. *
  30. *Purpose:
  31. *       Both functions perform a consistency check on the heap. The old
  32. *       _heapset used to fill free blocks with _fill, in addition to
  33. *       performing the consistency check. The current _heapset ignores the
  34. *       passed parameter and just returns _heapchk.
  35. *
  36. *Entry:
  37. *       For heapchk()
  38. *           No arguments
  39. *       For heapset()
  40. *           int _fill - ignored
  41. *
  42. *Exit:
  43. *       Returns one of the following values:
  44. *
  45. *           _HEAPOK         - completed okay
  46. *           _HEAPEMPTY      - heap not initialized
  47. *           _HEAPBADBEGIN   - can't find initial header info
  48. *           _HEAPBADNODE    - malformed node somewhere
  49. *
  50. *       Debug version prints out a diagnostic message if an error is found
  51. *       (see errmsg[] above).
  52. *
  53. *       NOTE:  Add code to support memory regions.
  54. *
  55. *Uses:
  56. *
  57. *Exceptions:
  58. *
  59. *******************************************************************************/
  60.  
  61. int __cdecl _heapchk (void)
  62. {
  63.     int retcode = _HEAPOK;
  64.  
  65.     _mlock(_HEAP_LOCK);
  66.     if ( __sbh_heap_check() < 0 )
  67.         retcode = _HEAPBADNODE;
  68.     _munlock(_HEAP_LOCK);
  69.  
  70.     if (!HeapValidate(_crtheap, 0, NULL))
  71.     {
  72.         if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
  73.         {
  74.             _doserrno = ERROR_CALL_NOT_IMPLEMENTED;
  75.             errno = ENOSYS;
  76.         }
  77.         else
  78.             retcode = _HEAPBADNODE;
  79.     }
  80.     return retcode;
  81. }
  82.  
  83. /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
  84.  
  85. int __cdecl _heapset (
  86.         unsigned int _fill
  87.         )
  88. {
  89.         return _heapchk();
  90. }
  91.  
  92.  
  93.  
  94. #else  /* WINHEAP */
  95.  
  96.  
  97. #include <cruntime.h>
  98. #include <heap.h>
  99. #include <malloc.h>
  100. #include <mtdll.h>
  101. #include <stddef.h>
  102. #include <string.h>
  103.  
  104. static int __cdecl _heap_checkset(unsigned int _fill);
  105.  
  106. /* Debug error values */
  107. #define _EMPTYHEAP   0
  108. #define _BADROVER    1
  109. #define _BADRANGE    2
  110. #define _BADSENTINEL 3
  111. #define _BADEMPTY    4
  112. #define _EMPTYLOOP   5
  113. #define _BADFREE     6
  114. #define _BADORDER    7
  115.  
  116.  
  117. #define _PRINTERR(msg)
  118.  
  119.  
  120.  
  121. /***
  122. *int _heapchk()      - Validate the heap
  123. *int _heapset(_fill) - Validate the heap and fill in free entries
  124. *
  125. *Purpose:
  126. *   Performs a consistency check on the heap.
  127. *
  128. *Entry:
  129. *   For heapchk()
  130. *       No arguments
  131. *   For heapset()
  132. *       int _fill - value to be used as filler in free entries
  133. *
  134. *Exit:
  135. *   Returns one of the following values:
  136. *
  137. *       _HEAPOK          - completed okay
  138. *       _HEAPEMPTY       - heap not initialized
  139. *       _HEAPBADBEGIN    - can't find initial header info
  140. *       _HEAPBADNODE     - malformed node somewhere
  141. *
  142. *   Debug version prints out a diagnostic message if an error is found
  143. *   (see errmsg[] above).
  144. *
  145. *   NOTE:  Add code to support memory regions.
  146. *
  147. *Uses:
  148. *
  149. *Exceptions:
  150. *
  151. *******************************************************************************/
  152.  
  153. int __cdecl _heapchk(void)
  154. {
  155.     return(_heap_checkset((unsigned int)_HEAP_NOFILL));
  156. }
  157.  
  158.  
  159. int __cdecl _heapset (
  160.     unsigned int _fill
  161.     )
  162. {
  163.     return(_heap_checkset(_fill));
  164. }
  165.  
  166.  
  167. /***
  168. *static int _heap_checkset(_fill) - check the heap and fill in the
  169. *   free entries
  170. *
  171. *Purpose:
  172. *   Workhorse routine for both _heapchk() and _heapset().
  173. *
  174. *Entry:
  175. *   int _fill - either _HEAP_NOFILL or a value to be used as filler in
  176. *              free entries
  177. *
  178. *Exit:
  179. *   See description of _heapchk()/_heapset()
  180. *
  181. *******************************************************************************/
  182.  
  183. static int __cdecl _heap_checkset (
  184.     unsigned int _fill
  185.     )
  186. {
  187.     REG1 _PBLKDESC pdesc;
  188.     REG2 _PBLKDESC pnext;
  189.     int roverfound=0;
  190.     int retval = _HEAPOK;
  191.  
  192.     /*
  193.      * lock the heap
  194.      */
  195.  
  196.     _mlock(_HEAP_LOCK);
  197.  
  198.     /*
  199.      * Validate the sentinel
  200.      */
  201.  
  202.     if (_heap_desc.sentinel.pnextdesc != NULL) {
  203.         _PRINTERR(_BADSENTINEL);
  204.         retval = _HEAPBADNODE;
  205.         goto done;
  206.     }
  207.  
  208.     /*
  209.      * Test for an empty heap
  210.      */
  211.  
  212.     if ( (_heap_desc.pfirstdesc == &_heap_desc.sentinel) &&
  213.          (_heap_desc.proverdesc == &_heap_desc.sentinel) ) {
  214.         retval = _HEAPEMPTY;
  215.         goto done;
  216.     }
  217.  
  218.     /*
  219.      * Get and validate the first descriptor
  220.      */
  221.  
  222.     if ((pdesc = _heap_desc.pfirstdesc) == NULL) {
  223.         _PRINTERR(_EMPTYHEAP);
  224.         retval = _HEAPBADBEGIN;
  225.         goto done;
  226.     }
  227.  
  228.     /*
  229.      * Walk the heap descriptor list
  230.      */
  231.  
  232.     while (pdesc != &_heap_desc.sentinel) {
  233.  
  234.         /*
  235.          * Make sure address for this entry is in range.
  236.          */
  237.  
  238.         if ( (_ADDRESS(pdesc) < _ADDRESS(_heap_desc.pfirstdesc)) ||
  239.              (_ADDRESS(pdesc) > _heap_desc.sentinel.pblock) ) {
  240.             _PRINTERR(_BADRANGE);
  241.             retval = _HEAPBADNODE;
  242.             goto done;
  243.         }
  244.  
  245.         pnext = pdesc->pnextdesc;
  246.  
  247.         /*
  248.          * Make sure the blocks corresponding to pdesc and pnext are
  249.          * in proper order.
  250.          */
  251.  
  252.         if ( _ADDRESS(pdesc) >= _ADDRESS(pnext) ) {
  253.             _PRINTERR(_BADORDER);
  254.             retval = _HEAPBADNODE;
  255.             goto done;
  256.         }
  257.  
  258.         /*
  259.          * Check the backpointer.
  260.          */
  261.  
  262.         if (_IS_INUSE(pdesc) || _IS_FREE(pdesc)) {
  263.  
  264.             if (!_CHECK_PDESC(pdesc)) {
  265.                 retval = _HEAPBADPTR;
  266.                 goto done;
  267.             }
  268.         }
  269.  
  270.         /*
  271.          * Check for proverdesc
  272.          */
  273.  
  274.         if (pdesc == _heap_desc.proverdesc)
  275.             roverfound++;
  276.  
  277.         /*
  278.          * If it is free, fill it in if appropriate
  279.          */
  280.  
  281.         if ( _IS_FREE(pdesc) && (_fill != _HEAP_NOFILL) )
  282.             memset( (void *)((unsigned)_ADDRESS(pdesc)+_HDRSIZE),
  283.             _fill, _BLKSIZE(pdesc) );
  284.  
  285.         /*
  286.          * Onto the next block
  287.          */
  288.  
  289.         pdesc = pnext;
  290.     }
  291.  
  292.     /*
  293.      * Make sure we found 1 and only 1 rover
  294.      */
  295.  
  296.     if (_heap_desc.proverdesc == &_heap_desc.sentinel)
  297.         roverfound++;
  298.  
  299.     if (roverfound != 1) {
  300.         _PRINTERR(_BADROVER);
  301.         retval = _HEAPBADBEGIN;
  302.         goto done;
  303.     }
  304.  
  305.     /*
  306.      * Walk the empty list.  We can't really compare values against
  307.      * anything but we may loop forever or may cause a fault.
  308.      */
  309.  
  310.     pdesc = _heap_desc.emptylist;
  311.  
  312.     while (pdesc != NULL) {
  313.  
  314.  
  315.         pnext = pdesc->pnextdesc;
  316.  
  317.         /*
  318.          * Header should only appear once
  319.          */
  320.  
  321.         if (pnext == _heap_desc.emptylist) {
  322.             _PRINTERR(_EMPTYLOOP)
  323.             retval = _HEAPBADPTR;
  324.             goto done;
  325.         }
  326.  
  327.         pdesc = pnext;
  328.  
  329.     }
  330.  
  331.  
  332.     /*
  333.      * Common return
  334.      */
  335.  
  336. done:
  337.     /*
  338.      * release the heap lock
  339.      */
  340.  
  341.     _munlock(_HEAP_LOCK);
  342.  
  343.     return(retval);
  344.  
  345. }
  346.  
  347.  
  348. #endif  /* WINHEAP */
  349.