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.

265 lines
7.4 KiB

  1. /*** mem.c - Memory Manager
  2. *
  3. * Microsoft Confidential
  4. * Copyright (C) Microsoft Corporation 1993-1994
  5. * All Rights Reserved.
  6. *
  7. * Author:
  8. * Benjamin W. Slivka
  9. *
  10. * History:
  11. * 10-Aug-1993 bens Initial version
  12. * 11-Aug-1993 bens Lift code from STOCK.EXE win app
  13. * 12-Aug-1993 bens Get strings from memory.msg
  14. * 01-Sep-1993 bens Add NULL pointer checks to MMAssert and MMStrDup
  15. * 18-Mar-1994 bens Make sure non-assert build works; rename
  16. * 18-May-1994 bens Allow turning off MemCheckHeap() in debug build
  17. * (it can really, really slow things down!)
  18. *
  19. * Functions:
  20. * MemAlloc - Allocate memory block
  21. * MemFree - Free memory block
  22. * MemStrDup - Duplicate string to new memory block
  23. *
  24. * Functions available in ASSERT build:
  25. * MemAssert - Assert that pointer was allocated by MemAlloc
  26. * MemCheckHeap - Check entire memory heap
  27. * MemListHeap - List all heap entries
  28. * MemGetSize - Return allocated size of memory block
  29. * MemSetCheckHeap - Control whether MemCheckHeap is done on every
  30. * every MemAlloc and MemFree!
  31. */
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include <memory.h>
  35. #include <malloc.h>
  36. #include "types.h"
  37. #include "asrt.h"
  38. #ifdef ASSERT // Must be after asrt.h!
  39. #include "mem.h"
  40. #include "mem.msg"
  41. /*** MEMSIG - memory signature
  42. *
  43. * This is placed at the front and end of every dynamic memory
  44. * alloction in DEBUG builds. The pointer has to be unaligned for
  45. * RISC machines.
  46. */
  47. typedef ULONG MEMSIG; /* ms - memory signature */
  48. typedef MEMSIG UNALIGNED *PMEMSIG; /* pms */
  49. #define msHEAD 0x12345678L // Head signature
  50. #define msTAIL 0x87654321L // Tail signature
  51. #define msBAD 0L // Bad signature
  52. #define cmsTAIL 2 // Number of tail signatures
  53. typedef struct mh_t {
  54. MEMSIG ms; // Head signature (msHEAD)
  55. unsigned cb; // Size of user block
  56. struct mh_t *pmhNext; // Next block
  57. struct mh_t *pmhPrev; // Previous block
  58. // char ach[?]; // User block; length is cb
  59. // MEMSIG ms[cmsTAIL]; // Tail signature area (msTAIL...)
  60. } MEMHDR; /* mh - memory header */
  61. typedef MEMHDR *PMEMHDR; /* pmh */
  62. #define PMHFromPV(pv) ((PMEMHDR)((char *)pv - sizeof(MEMHDR)))
  63. #define PVFromPMH(pmh) ((void *)((char *)pmh+sizeof(MEMHDR)))
  64. STATIC PMEMHDR pmhList=NULL; // List of memory blocks
  65. STATIC BOOL fDoCheckHeap=TRUE; // TRUE => check heap regularly
  66. void MemSetCheckHeap(BOOL f)
  67. {
  68. fDoCheckHeap = f;
  69. }
  70. void MMCheckHeap(char *pszFile, int iLine)
  71. {
  72. PMEMHDR pmh;
  73. PMEMHDR pmhPrev = NULL;
  74. for (pmh = pmhList; pmh != NULL; pmh = pmh->pmhNext) {
  75. MMAssert(PVFromPMH(pmh),pszFile,iLine);
  76. AssertSub(pmh->pmhPrev==pmhPrev,pszFile,iLine);
  77. pmhPrev = pmh;
  78. }
  79. }
  80. void MMListHeap(char *pszFile, int iLine)
  81. {
  82. PMEMHDR pmh;
  83. if (fDoCheckHeap) {
  84. if (pmhList != NULL) {
  85. printf("\n");
  86. for (pmh = pmhList; pmh != NULL; pmh = pmh->pmhNext) {
  87. printf("alloc at %08lX is %d bytes\n", PVFromPMH(pmh), pmh->cb);
  88. }
  89. MMCheckHeap(pszFile,iLine);
  90. printf("\n");
  91. }
  92. }
  93. }
  94. void MMAssert(void *pv, char *pszFile, int iLine)
  95. {
  96. int i;
  97. PMEMHDR pmh;
  98. PMEMSIG pms;
  99. AssertSub(pv!=NULL,pszFile,iLine);
  100. pmh = PMHFromPV(pv);
  101. if ((void *)pmh > pv) { // Pointer wrapped
  102. AssertForce(pszMEMERR_NULL_POINTER,pszFile,iLine);
  103. }
  104. // Test head signature
  105. if (pmh->ms != msHEAD) {
  106. AssertForce(pszMEMERR_BAD_HEAD_SIG,pszFile,iLine);
  107. }
  108. // Test tail signatures
  109. pms = (PMEMSIG)( (char *)pmh + sizeof(MEMHDR) + pmh->cb );
  110. for (i=0; i<cmsTAIL; i++) {
  111. if (*pms++ != msTAIL) {
  112. AssertForce(pszMEMERR_BAD_HEAD_SIG,pszFile,iLine);
  113. }
  114. }
  115. } /* MMAssert */
  116. void MMFree(void *pv, char *pszFile, int iLine)
  117. {
  118. PMEMHDR pmh;
  119. MMAssert(pv,pszFile,iLine);
  120. //** Check heap if enabled
  121. if (fDoCheckHeap) {
  122. MMCheckHeap(pszFile,iLine);
  123. }
  124. pmh = PMHFromPV(pv);
  125. // Make previous block point to next block
  126. if (pmh->pmhPrev != NULL) { // pmh is not at front of list
  127. // before: a->p->?
  128. pmh->pmhPrev->pmhNext = pmh->pmhNext;
  129. // after: a->?
  130. }
  131. else { // pmh is at front of list
  132. // before: list->p->?
  133. pmhList = pmh->pmhNext;
  134. // after: list->?
  135. }
  136. // Make next block point to previous block
  137. if (pmh->pmhNext != NULL) { // pmh is not at end of list
  138. // before: ?<-p<->a
  139. pmh->pmhNext->pmhPrev = pmh->pmhPrev;
  140. // after: ?<-a
  141. }
  142. // Obliterate signature
  143. pmh->ms = msBAD;
  144. // Free memory
  145. free((char *)pmh);
  146. }
  147. void *MMAlloc(unsigned cb, char *pszFile, int iLine)
  148. {
  149. unsigned cbAlloc;
  150. int i;
  151. PMEMHDR pmh;
  152. PMEMSIG pms;
  153. if (fDoCheckHeap) {
  154. MMCheckHeap(pszFile,iLine);
  155. }
  156. // Solves alignment problems on the RISCs
  157. cb = (cb+3) & ~3;
  158. cbAlloc = cb+sizeof(MEMHDR)+sizeof(MEMSIG)*cmsTAIL;
  159. pmh = malloc(cbAlloc);
  160. if (pmh != NULL) {
  161. pmh->ms = msHEAD; // Store head signature
  162. pmh->cb = cb; // Store size of user block
  163. // Add block to front of list (Easiest code!)
  164. if (pmhList != NULL) { // List is not empty
  165. pmhList->pmhPrev = pmh; // Point old top block back at us
  166. }
  167. pmh->pmhNext = pmhList; // Next element is old top block
  168. pmh->pmhPrev = NULL; // We are first, so no prev block
  169. pmhList = pmh; // Make ourselves first
  170. // Fill in tail signatures
  171. pms = (PMEMSIG)( (char *)pmh + sizeof(MEMHDR) + pmh->cb );
  172. for (i=0; i<cmsTAIL; i++) {
  173. *pms++ = msTAIL;
  174. }
  175. return PVFromPMH(pmh);
  176. }
  177. else {
  178. AssertForce(pszMEMERR_OUT_OF_MEMORY,pszFile,iLine);
  179. /*
  180. printf("panic: out of memory in MMAlloc\n");
  181. printf("\n");
  182. printf("Dump of heap (newest alloc to oldest)\n");
  183. printf("\n");
  184. printf("Size Addr Content\n");
  185. printf("----- ---- -------\n");
  186. for (pmh = pmhList; pmh != NULL; pmh = pmh->pmhNext) {
  187. pch = PVFromPMH(pmh);
  188. printf("%5d %04x %s\n",pmh->cb,(unsigned)pch,pch);
  189. }
  190. return NULL;
  191. */
  192. }
  193. }
  194. char *MMStrDup(char *pch, char *pszFile, int iLine)
  195. {
  196. unsigned cb;
  197. char *pchDst;
  198. //** Make sure pointer is not null.
  199. // NOTE: pch does not have to be a string we dynamically allocated!
  200. AssertSub(pch!=NULL,pszFile,iLine);
  201. cb = strlen(pch)+1; // Count NUL terminator
  202. pchDst = MMAlloc(cb,pszFile,iLine); // Alloc new copy
  203. if (pchDst != NULL) { // Success
  204. memcpy(pchDst,pch,cb); // Copy string
  205. }
  206. return pchDst; // Return string copy
  207. }
  208. int MemGetSize(void *pv)
  209. {
  210. PMEMHDR pmh;
  211. MMAssert(pv,__FILE__,__LINE__);
  212. pmh = PMHFromPV(pv);
  213. return pmh->cb;
  214. }
  215. #endif // !ASSERT