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.

461 lines
8.7 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: Alloc.cpp
  7. //
  8. // Contents: Allocation routines
  9. //
  10. // Classes:
  11. //
  12. // Notes:
  13. //
  14. // History: 05-Nov-97 rogerg Created.
  15. //
  16. //--------------------------------------------------------------------------
  17. #include "lib.h"
  18. #ifdef _DEBUG
  19. extern DWORD g_dwDebugLeakDetection;
  20. #endif // _DEBUG
  21. //+-------------------------------------------------------------------
  22. //
  23. // Function: ::operator new
  24. //
  25. // Synopsis: Our operator new implementation
  26. //
  27. // Arguments: [size] -- Size of memory to allocate
  28. //
  29. //
  30. // Notes:
  31. //
  32. //--------------------------------------------------------------------
  33. inline void* __cdecl operator new (size_t size)
  34. {
  35. return(ALLOC(size));
  36. }
  37. //+-------------------------------------------------------------------
  38. //
  39. // Function: ::operator delete
  40. //
  41. // Synopsis: Our operator deleteimplementation
  42. //
  43. // Arguments: lpv-- Pointer to memory to free
  44. //
  45. //
  46. // Notes:
  47. //
  48. //--------------------------------------------------------------------
  49. inline void __cdecl operator delete(void FAR* lpv)
  50. {
  51. FREE(lpv);
  52. }
  53. //
  54. // Allocator for MIDL stubs
  55. //
  56. //+-------------------------------------------------------------------
  57. //
  58. // Function: MIDL_user_allocate
  59. //
  60. // Synopsis:
  61. //
  62. // Arguments: lpv-- Pointer to memory to free
  63. //
  64. //
  65. // Notes:
  66. //
  67. //--------------------------------------------------------------------
  68. extern "C" void __RPC_FAR * __RPC_API
  69. MIDL_user_allocate(
  70. IN size_t len
  71. )
  72. {
  73. return ALLOC(len);
  74. }
  75. //+-------------------------------------------------------------------
  76. //
  77. // Function: MIDL_user_free
  78. //
  79. // Synopsis:
  80. //
  81. // Arguments: ptr-- Pointer to memory to free
  82. //
  83. //
  84. // Notes:
  85. //
  86. //--------------------------------------------------------------------
  87. extern "C" void __RPC_API
  88. MIDL_user_free(
  89. IN void __RPC_FAR * ptr
  90. )
  91. {
  92. FREE(ptr);
  93. }
  94. //+---------------------------------------------------------------------------
  95. //
  96. // function: ALLOC, public
  97. //
  98. // Synopsis: memory allocator
  99. //
  100. // Arguments: [cb] - requested size of memory to alloc.
  101. //
  102. // Returns: Pointer to newly allocated memory, NULL on failure
  103. //
  104. // Modifies:
  105. //
  106. // History: 05-Nov-97 rogerg Created.
  107. //
  108. //----------------------------------------------------------------------------
  109. LPVOID ALLOC(ULONG cb)
  110. {
  111. void *pv;
  112. pv = LocalAlloc(LMEM_FIXED,cb);
  113. #ifdef _DEBUG
  114. if (NULL != pv) // under debug always initialize to -1 to catch unitialize errors.
  115. {
  116. memset(pv,MEMINITVALUE,cb);
  117. // add entry to arena
  118. ADDENTRY(pv,cb);
  119. }
  120. #endif // _DEBUG
  121. return pv;
  122. }
  123. //+---------------------------------------------------------------------------
  124. //
  125. // function: FREE, public
  126. //
  127. // Synopsis: memory destructor
  128. //
  129. // Arguments: [pv] - pointer to memory to be released.
  130. //
  131. // Returns:
  132. //
  133. // Modifies:
  134. //
  135. // History: 05-Nov-97 rogerg Created.
  136. //
  137. //----------------------------------------------------------------------------
  138. void FREE(void* pv)
  139. {
  140. #ifdef _DEBUG
  141. if (NULL != pv) // under debug always initialize to -1 to catch unitialize errors.
  142. {
  143. UINT cb;
  144. Assert(LMEM_INVALID_HANDLE != LocalFlags(pv));
  145. cb = (UINT)LocalSize(pv); // returns zero on failure
  146. memset(pv,MEMFREEVALUE,cb);
  147. }
  148. FREEENTRY(pv);
  149. Assert(pv);
  150. #endif // _DEBUG
  151. LocalFree(pv);
  152. }
  153. //+---------------------------------------------------------------------------
  154. //
  155. // function: REALLOC, public
  156. //
  157. // Synopsis: reallocs memory
  158. //
  159. // Arguments: [pv] - pointer to memory to be released.
  160. // [cb] - size to resize the memory to.
  161. //
  162. // Returns:
  163. //
  164. // Modifies:
  165. //
  166. // History: 22-Jul-98 rogerg Created.
  167. //
  168. //----------------------------------------------------------------------------
  169. LPVOID REALLOC(void *pv,ULONG cb)
  170. {
  171. Assert(pv);
  172. FREEENTRY(pv);
  173. pv = LocalReAlloc(pv,cb,LMEM_MOVEABLE);
  174. ADDENTRY(pv,cb);
  175. return pv;
  176. }
  177. #if MEMLEAKDETECTION
  178. #define ARENA_SIZE 5000
  179. MEMARENA *g_MemChk = NULL;
  180. BOOL g_InitArenaFailed = FALSE;
  181. ULONG g_AllocNumber = 0;
  182. ULONG g_FreeNumber = 0;
  183. ULONG g_ulAssertonAlloc = -1; // set this to the leak number for getting the stack trace.
  184. CRITICAL_SECTION g_ArenaCriticalSection;
  185. //+---------------------------------------------------------------------------
  186. //
  187. // function: InitArena, private
  188. //
  189. // Synopsis: Initializes our memory leak arena
  190. //
  191. // Arguments: .
  192. //
  193. // Returns: TRUE if Arena was successsfully initialized
  194. //
  195. // Modifies:
  196. //
  197. // History: 05-Nov-97 rogerg Created.
  198. //
  199. //----------------------------------------------------------------------------
  200. BOOL InitArena()
  201. {
  202. int i = 0;
  203. Assert(g_dwDebugLeakDetection);
  204. if (!g_dwDebugLeakDetection || g_InitArenaFailed)
  205. {
  206. return FALSE;
  207. }
  208. // if g_MemChk is NULL Allocate space for it,
  209. // else we are already initialized
  210. if (g_MemChk == NULL)
  211. {
  212. g_MemChk = (MEMARENA *) CoTaskMemAlloc(sizeof(MEMARENA) * (ARENA_SIZE + 1)) ;
  213. if (g_MemChk == NULL)
  214. {
  215. AssertSz(0,"Unable to Initialize LeakDetection");
  216. g_InitArenaFailed = TRUE;
  217. return FALSE;
  218. }
  219. g_MemChk[ARENA_SIZE - 1].Free = 'END ';
  220. while(g_MemChk[i].Free != 'END ' )
  221. {
  222. g_MemChk[i].Free = 'FREE';
  223. i++ ;
  224. }
  225. g_AllocNumber = 0;
  226. g_FreeNumber = 0;
  227. InitializeCriticalSection(&g_ArenaCriticalSection);
  228. }
  229. return TRUE;
  230. }
  231. //+---------------------------------------------------------------------------
  232. //
  233. // function: AddEntry, private
  234. //
  235. // Synopsis: Adds an entry to our memory leak arena
  236. //
  237. // Arguments: [lpv] - pointer to add to arena
  238. // [size] - size of pointer to add to the arena
  239. //
  240. // Returns:
  241. //
  242. // Modifies:
  243. //
  244. // History: 05-Nov-97 rogerg Created.
  245. //
  246. //----------------------------------------------------------------------------
  247. void AddEntry( void *lpv, unsigned long size)
  248. {
  249. LPMEMARENA lpMem = g_MemChk;
  250. CCriticalSection critsect(&g_ArenaCriticalSection,GetCurrentThreadId());
  251. int i = 0;
  252. if (!g_dwDebugLeakDetection)
  253. {
  254. return;
  255. }
  256. if (!InitArena())
  257. {
  258. return;
  259. }
  260. critsect.Enter();
  261. // Find first available entry.
  262. while(g_MemChk[i].Free != 'FREE' && g_MemChk[i].Free != 'END ')
  263. {
  264. i++;
  265. }
  266. if ( g_MemChk[i].Free != 'END ' )
  267. {
  268. g_AllocNumber++;
  269. g_MemChk[i].Free = 'Ptr ';
  270. g_MemChk[i].lpv = lpv;
  271. g_MemChk[i].size = size;
  272. g_MemChk[i].Order = g_AllocNumber;
  273. if (g_AllocNumber == g_ulAssertonAlloc)
  274. {
  275. AssertSz(0,"Allocating AllocNumber");
  276. }
  277. }
  278. else
  279. {
  280. AssertSz(0,"Arena is full");
  281. }
  282. critsect.Leave();
  283. return;
  284. }
  285. //+---------------------------------------------------------------------------
  286. //
  287. // function: FreeEntry, private
  288. //
  289. // Synopsis: removes an entry from the memory arena
  290. //
  291. // Arguments: [lpv] - pointer to remove from the arena
  292. //
  293. // Returns:
  294. //
  295. // Modifies:
  296. //
  297. // History: 05-Nov-97 rogerg Created.
  298. //
  299. //----------------------------------------------------------------------------
  300. void FreeEntry ( void *lpv )
  301. {
  302. int i = 0;
  303. BOOL fFoundEntry = FALSE;
  304. CCriticalSection critsect(&g_ArenaCriticalSection,GetCurrentThreadId());
  305. if (!g_dwDebugLeakDetection)
  306. {
  307. return;
  308. }
  309. if (!InitArena())
  310. {
  311. return;
  312. }
  313. critsect.Enter();
  314. g_FreeNumber++;
  315. // Find entry.
  316. while( g_MemChk[i].Free != 'END ' )
  317. {
  318. if ( g_MemChk[i].lpv == lpv )
  319. {
  320. g_MemChk[i].Free = 'FREE';
  321. g_MemChk[i].lpv = NULL;
  322. g_MemChk[i].size = 0;
  323. g_MemChk[i].Order = 0;
  324. fFoundEntry = TRUE;
  325. break;
  326. }
  327. i++;
  328. }
  329. if (!fFoundEntry)
  330. {
  331. char buf[255];
  332. wsprintfA(buf, "??Freeing block not in mem arena %X\n", lpv);
  333. AssertSz(0,buf);
  334. }
  335. critsect.Leave();
  336. }
  337. //+---------------------------------------------------------------------------
  338. //
  339. // function: WalkArena, private
  340. //
  341. // Synopsis: walks arena asserting if finds any leaks.
  342. //
  343. // Arguments:
  344. //
  345. // Returns:
  346. //
  347. // Modifies:
  348. //
  349. // History: 05-Nov-97 rogerg Created.
  350. //
  351. //----------------------------------------------------------------------------
  352. void WalkArena()
  353. {
  354. int i = 0;
  355. if (!g_dwDebugLeakDetection)
  356. {
  357. return;
  358. }
  359. if (!InitArena())
  360. {
  361. return;
  362. }
  363. while( g_MemChk[i].Free != 'END ' )
  364. {
  365. if ( g_MemChk[i].Free != 'FREE' )
  366. {
  367. AssertSz(0,"You Have a Leak");
  368. }
  369. i++;
  370. }
  371. g_MemChk = NULL;
  372. }
  373. #endif // MEMLEAKDETECTION