PageRenderTime 54ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/v1.9-final/mem/mem.c

https://github.com/simX/d2x-xl
C | 534 lines | 405 code | 81 blank | 48 comment | 75 complexity | 18afcf9f12cc7dbd37b718f9328c6e34 MD5 | raw file
Possible License(s): GPL-2.0
  1. /* $Id: mem.c,v 1.12 2003/11/26 12:39:00 btb Exp $ */
  2. /*
  3. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  4. SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
  5. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  6. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  7. IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  8. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  9. FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  10. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
  11. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  12. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
  13. */
  14. /*
  15. *
  16. * Files for debugging memory allocator
  17. *
  18. *
  19. */
  20. #ifdef HAVE_CONFIG_H
  21. #include <conf.h>
  22. #endif
  23. // Warning ("MEM: Too many D2_ALLOC's!");
  24. // Warning ("MEM: Malloc returnd an already alloced block!");
  25. // Warning ("MEM: Malloc Failed!");
  26. // Warning ("MEM: Freeing the NULL pointer!");
  27. // Warning ("MEM: Freeing a non-malloced pointer!");
  28. // Warning ("MEM: %d/%d check bytes were overwritten at the end of %8x", ec, CHECKSIZE, buffer );
  29. // Warning ("MEM: %d blocks were left allocated!", numleft);
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #ifdef __macosx__
  34. # include <sys/malloc.h>
  35. #else
  36. # include <malloc.h>
  37. #endif
  38. #include "pstypes.h"
  39. #include "mono.h"
  40. #include "error.h"
  41. #include "u_mem.h"
  42. int bShowMemInfo = 0;
  43. #if DBG_MALLOC
  44. # define CHECKID1 1977
  45. # define CHECKID2 1979
  46. #endif
  47. #ifdef D2X_MEM_HANDLER
  48. #define LONG_MEM_ID 1
  49. #define MEMSTATS 0
  50. #if DBG_MALLOC
  51. # define FULL_MEM_CHECKING 1
  52. #else
  53. # define FULL_MEM_CHECKING 0
  54. #endif
  55. #if FULL_MEM_CHECKING
  56. #define CHECKSIZE 16
  57. #define CHECKBYTE 0xFC
  58. #define MEM_MAX_INDEX 1000000
  59. static void *pMallocBase [MEM_MAX_INDEX];
  60. static unsigned int nMallocSize [MEM_MAX_INDEX];
  61. static unsigned char bPresent [MEM_MAX_INDEX];
  62. static char * szFilename [MEM_MAX_INDEX];
  63. static char * szVarname [MEM_MAX_INDEX];
  64. static int nLineNum [MEM_MAX_INDEX];
  65. static int nId [MEM_MAX_INDEX];
  66. static int nBytesMalloced = 0;
  67. static int nFreeList [MEM_MAX_INDEX];
  68. static int iFreeList = 0;
  69. static int bMemInitialized = 0;
  70. static int nLargestIndex = 0;
  71. static int nMemId = 0;
  72. int bOutOfMemory = 0;
  73. //------------------------------------------------------------------------------
  74. #define MEM_INIT(_b) memset (_b, 0, sizeof (_b))
  75. void MemInit ()
  76. {
  77. if (!bMemInitialized) {
  78. int i;
  79. bMemInitialized = 1;
  80. MEM_INIT (pMallocBase);
  81. MEM_INIT (nMallocSize);
  82. MEM_INIT (bPresent);
  83. MEM_INIT (szFilename);
  84. MEM_INIT (szVarname);
  85. MEM_INIT (nLineNum);
  86. for (i = 0; i < MEM_MAX_INDEX - 1; i++)
  87. nFreeList [i] = i + 1;
  88. nFreeList [i] = -1;
  89. nLargestIndex = 0;
  90. nMemId = 0;
  91. atexit (MemDisplayBlocks);
  92. }
  93. }
  94. //------------------------------------------------------------------------------
  95. void PrintInfo (int id)
  96. {
  97. LogErr ("\tBlock '%s' created in %s, line %d.\n",
  98. szVarname [id], szFilename [id], nLineNum [id]);
  99. }
  100. //------------------------------------------------------------------------------
  101. int MemFindId (void *buffer)
  102. {
  103. int id;
  104. buffer = (void *) (((int *) buffer) - 2);
  105. id = *((int *) buffer);
  106. if ((id < 0) || (id > nLargestIndex))
  107. return -1;
  108. else if (!bPresent [id])
  109. return -1;
  110. else if (pMallocBase [id] != buffer)
  111. return -1;
  112. else
  113. return id;
  114. }
  115. //------------------------------------------------------------------------------
  116. int MemCheckIntegrity (int block_number)
  117. {
  118. int i, nErrorCount;
  119. ubyte *pCheckData;
  120. pCheckData = (ubyte *) ((char *) pMallocBase [block_number] + nMallocSize [block_number] + 2 * sizeof (int));
  121. nErrorCount = 0;
  122. for (i = 0; i < CHECKSIZE; i++)
  123. if (pCheckData [i] != CHECKBYTE) {
  124. nErrorCount++;
  125. LogErr ("OA: %p ", pCheckData + i);
  126. }
  127. if (nErrorCount && !bOutOfMemory) {
  128. LogErr ("\nMEM_OVERWRITE: Memory after the end of allocated block overwritten.\n");
  129. PrintInfo (block_number);
  130. LogErr ("\t%d/%d check bytes were overwritten.\n", nErrorCount, CHECKSIZE);
  131. Int3 ();
  132. }
  133. return nErrorCount;
  134. }
  135. //------------------------------------------------------------------------------
  136. void _CDECL_ MemDisplayBlocks (void)
  137. {
  138. int i, numleft;
  139. if (!bMemInitialized)
  140. return;
  141. #if MEMSTATS
  142. if (bMemStatsFileInitialized) {
  143. unsigned long nFreeMem = FreeMem ();
  144. fprintf (sMemStatsFile,
  145. "\n%9u bytes free before closing MEMSTATS file.", nFreeMem);
  146. fprintf (sMemStatsFile, "\nMemory Stats File Closed.");
  147. fclose (sMemStatsFile);
  148. }
  149. #endif // end of ifdef memstats
  150. numleft = 0;
  151. for (i = 0; i <= nLargestIndex; i++) {
  152. if (bPresent [i] && !bOutOfMemory) {
  153. numleft++;
  154. if (bShowMemInfo) {
  155. LogErr ("\nMEM_LEAKAGE: Memory block has not been freed.\n");
  156. PrintInfo (i);
  157. }
  158. MemFree ((void *) pMallocBase [i]);
  159. }
  160. }
  161. #if DBG_MALLOC
  162. if (numleft && !bOutOfMemory)
  163. Warning ("MEM: %d blocks were left allocated!\n", numleft);
  164. #endif
  165. }
  166. //------------------------------------------------------------------------------
  167. void MemValidateHeap ()
  168. {
  169. int i;
  170. for (i = 0; i < nLargestIndex; i++)
  171. if (bPresent [i])
  172. MemCheckIntegrity (i);
  173. }
  174. //------------------------------------------------------------------------------
  175. void MemPrintAll ()
  176. {
  177. FILE * ef;
  178. int i, size = 0;
  179. ef = fopen ("DESCENT.MEM", "wt");
  180. for (i = 0; i < nLargestIndex; i++)
  181. if (bPresent [i]) {
  182. size += nMallocSize [i];
  183. //fprintf (ef, "Var:%s\t File:%s\t Line:%d\t Size:%d Base:%x\n", szVarname [i], szFilename [i], Line [i], nMallocSize [i], pMallocBase [i]);
  184. fprintf (ef, "%12d bytes in %s declared in %s, line %d\n", nMallocSize [i], szVarname [i], szFilename [i], nLineNum [i] );
  185. }
  186. fprintf (ef, "%d bytes (%d Kbytes) allocated.\n", size, size/1024);
  187. fclose (ef);
  188. }
  189. #else
  190. //------------------------------------------------------------------------------
  191. static int bMemInitialized = 0;
  192. static unsigned int nSmallestAddress = 0xFFFFFFF;
  193. static unsigned int nLargestAddress = 0x0;
  194. static unsigned int nBytesMalloced = 0;
  195. void _CDECL_ MemDisplayBlocks ();
  196. #define CHECKSIZE 16
  197. #define CHECKBYTE 0xFC
  198. int bShowMemInfo = 0;
  199. void MemInit ()
  200. {
  201. bMemInitialized = 1;
  202. nSmallestAddress = 0xFFFFFFF;
  203. nLargestAddress = 0x0;
  204. atexit (MemDisplayBlocks);
  205. }
  206. //------------------------------------------------------------------------------
  207. void _CDECL_ MemDisplayBlocks (void)
  208. {
  209. if (!bMemInitialized)
  210. return;
  211. #if MEMSTATS
  212. if (bMemStatsFileInitialized) {
  213. unsigned long nFreeMem = FreeMem ();
  214. fprintf (sMemStatsFile,
  215. "\n%9u bytes free before closing MEMSTATS file.", nFreeMem);
  216. fprintf (sMemStatsFile, "\nMemory Stats File Closed.");
  217. fclose (sMemStatsFile);
  218. }
  219. #endif // end of ifdef memstats
  220. if (nBytesMalloced) {
  221. LogErr ("\nMEM_LEAKAGE: %d bytes of memory have not been freed.\n", nBytesMalloced);
  222. }
  223. if (bShowMemInfo) {
  224. LogErr ("\n\nMEMORY USAGE:\n");
  225. LogErr (" %u Kbytes dynamic data\n", (nLargestAddress-nSmallestAddress+512)/1024);
  226. LogErr (" %u Kbytes code/static data.\n", (nSmallestAddress- (4*1024*1024)+512)/1024);
  227. LogErr (" ---------------------------\n");
  228. LogErr (" %u Kbytes required.\n", (nLargestAddress- (4*1024*1024)+512)/1024);
  229. }
  230. }
  231. //------------------------------------------------------------------------------
  232. void MemValidateHeap ()
  233. {
  234. }
  235. //------------------------------------------------------------------------------
  236. void MemPrintAll ()
  237. {
  238. }
  239. #endif
  240. //------------------------------------------------------------------------------
  241. void MemFree (void *buffer)
  242. {
  243. #if !DBG_MALLOC
  244. if (buffer)
  245. free (buffer);
  246. #else
  247. #if FULL_MEM_CHECKING
  248. int id;
  249. #endif
  250. if (!bMemInitialized)
  251. MemInit ();
  252. #if MEMSTATS
  253. {
  254. unsigned long nFreeMem = 0;
  255. if (bMemStatsFileInitialized) {
  256. nFreeMem = FreeMem ();
  257. fprintf (sMemStatsFile, "\n%9u bytes free before attempting: FREE", nFreeMem);
  258. }
  259. }
  260. #endif // end of ifdef memstats
  261. #ifdef FULL_MEM_CHECKING
  262. if (!(buffer || bOutOfMemory))
  263. #else
  264. if (!buffer)
  265. #endif
  266. {
  267. //LogErr ("\nMEM_FREE_NULL: An attempt was made to free the null pointer.\n");
  268. #if DBG_MALLOC
  269. //Warning ("MEM: Freeing the NULL pointer!");
  270. #endif
  271. Int3 ();
  272. return;
  273. }
  274. #if FULL_MEM_CHECKING
  275. # if LONG_MEM_ID
  276. buffer = (void *) (((char *) buffer) - 256);
  277. # endif
  278. id = MemFindId (buffer);
  279. if ((id == -1) && !bOutOfMemory) {
  280. LogErr ("\nMEM_FREE_NOMALLOC: An attempt was made to free a ptr that wasn't\nallocated with mem.h included.\n");
  281. #if DBG_MALLOC
  282. //Warning ("Freeing a non-allocated pointer!");
  283. #endif
  284. Int3 ();
  285. return;
  286. }
  287. MemCheckIntegrity (id);
  288. #endif
  289. #ifndef __macosx__
  290. nBytesMalloced -= *(((int *) buffer) - 1);
  291. #endif
  292. free (((int *) buffer) - 2);
  293. #if FULL_MEM_CHECKING
  294. bPresent [id] = 0;
  295. #if DBG_MALLOC
  296. if (id == CHECKID1)
  297. id = CHECKID1;
  298. if (id == CHECKID2)
  299. id = CHECKID2;
  300. #endif
  301. pMallocBase [id] = 0;
  302. nMallocSize [id] = 0;
  303. nFreeList [id] = iFreeList;
  304. iFreeList = id;
  305. # endif
  306. #endif
  307. }
  308. //------------------------------------------------------------------------------
  309. void *MemAlloc (unsigned int size, char * var, char * filename, int line, int fill_zero)
  310. {
  311. int *ptr;
  312. #ifndef _DEBUG
  313. if (!(ptr = (int *) malloc (size))) {
  314. #if 1//TRACE
  315. LogErr ("allocating %d bytes in %s:%d failed.\n", size, filename, line);
  316. #endif
  317. }
  318. else if (fill_zero)
  319. memset (ptr, 0, size);
  320. #else //!RELEASE
  321. #if FULL_MEM_CHECKING
  322. int id;
  323. #endif
  324. if (!bMemInitialized)
  325. MemInit ();
  326. #if MEMSTATS
  327. {
  328. unsigned long nFreeMem = 0;
  329. if (bMemStatsFileInitialized) {
  330. nFreeMem = FreeMem ();
  331. fprintf (sMemStatsFile, "\n%9u bytes free before attempting: MALLOC %9u bytes.", nFreeMem, size);
  332. }
  333. }
  334. #endif // end of ifdef memstats
  335. #if FULL_MEM_CHECKING
  336. if (iFreeList < 0) {
  337. LogErr ("\nMEM_OUT_OF_SLOTS: Not enough space in mem.c to hold all the mallocs.\n");
  338. LogErr ("\tBlock '%s' created in %s, line %d.\n", var, filename, line);
  339. Error ("Out of free memory slots");
  340. }
  341. id = iFreeList;
  342. iFreeList = nFreeList [iFreeList];
  343. if (id > nLargestIndex)
  344. nLargestIndex = id;
  345. if (id == -1) {
  346. LogErr ("\nMEM_OUT_OF_SLOTS: Not enough space in mem.c to hold all the mallocs.\n");
  347. LogErr ("\tBlock '%s' created in %s, line %d.\n", szVarname [id], szFilename [id], nLineNum [id]);
  348. Error ("Out of free memory slots");
  349. }
  350. #endif
  351. if (!size) {
  352. LogErr ("\nMEM_MALLOC_ZERO: Attempting to malloc 0 bytes.\n");
  353. LogErr ("\tVar %s, file %s, line %d.\n", var, filename, line);
  354. Error ("Tried to allocate block of 0 bytes");
  355. Int3 ();
  356. }
  357. #if LONG_MEM_ID
  358. ptr = malloc (size + CHECKSIZE + 2 * sizeof (int) + 256);
  359. #else
  360. ptr = malloc (size + CHECKSIZE + 2 * sizeof (int));
  361. #endif
  362. if (!ptr) {
  363. LogErr ("\nMEM_OUT_OF_MEMORY: Malloc returned NULL\n");
  364. LogErr ("\tVar %s, file %s, line %d.\n", var, filename, line);
  365. //Error ("MEM_OUT_OF_MEMORY");
  366. Int3 ();
  367. return NULL;
  368. }
  369. #if FULL_MEM_CHECKING
  370. pMallocBase [id] = ptr;
  371. nMallocSize [id] = size;
  372. szVarname [id] = var;
  373. szFilename [id] = filename;
  374. nLineNum [id] = line;
  375. if (nMemId == 20199)
  376. nMemId = nMemId;
  377. nId [id] = nMemId++;
  378. #if DBG_MALLOC
  379. if (id == CHECKID1)
  380. id = CHECKID1;
  381. if (id == CHECKID2)
  382. id = CHECKID2;
  383. #endif
  384. bPresent [id] = 1;
  385. #else
  386. {
  387. unsigned int base = (unsigned int) ptr;
  388. if (base < nSmallestAddress)
  389. nSmallestAddress = base;
  390. if ((base + size) > nLargestAddress)
  391. nLargestAddress = base+size;
  392. }
  393. #endif
  394. *ptr++ = id;
  395. *ptr++ = size;
  396. #if LONG_MEM_ID
  397. sprintf ((char *) ptr, "%s:%d", filename, line);
  398. ptr = (int *) (((char *) ptr) + 256);
  399. #endif
  400. nBytesMalloced += size;
  401. #if FULL_MEM_CHECKING
  402. memset ((char *) ptr + size, CHECKBYTE, CHECKSIZE);
  403. #endif
  404. if (fill_zero)
  405. memset (ptr, 0, size);
  406. #endif //!RELEASE
  407. return (void *) ptr;
  408. }
  409. //------------------------------------------------------------------------------
  410. void *MemRealloc (void * buffer, unsigned int size, char * var, char * filename, int line)
  411. {
  412. void *newbuffer = NULL;
  413. #if !DBG_MALLOC
  414. if (!size)
  415. MemFree (buffer);
  416. else if (!buffer)
  417. newbuffer = MemAlloc (size, var, filename, line, 0);
  418. else if (! (newbuffer = realloc (buffer, size))) {
  419. #if TRACE
  420. con_printf (CON_MALLOC, "reallocating %d bytes in %s:%d failed.\n", size, filename, line);
  421. #endif
  422. }
  423. #else
  424. int id;
  425. if (!bMemInitialized)
  426. MemInit ();
  427. if (!size)
  428. MemFree (buffer);
  429. else {
  430. newbuffer = MemAlloc (size, var, filename, line, 0);
  431. if (buffer) {
  432. id = MemFindId (buffer);
  433. if (nMallocSize [id] < size)
  434. size = nMallocSize [id];
  435. memcpy (newbuffer, buffer, size);
  436. MemFree (buffer);
  437. }
  438. }
  439. #endif
  440. return newbuffer;
  441. }
  442. //------------------------------------------------------------------------------
  443. char *MemStrDup (char *str, char *var, char *filename, int line)
  444. {
  445. char *newstr;
  446. int l = (int) strlen (str) + 1;
  447. if ((newstr = MemAlloc (l, var, filename, line, 0)))
  448. memcpy (newstr, str, l);
  449. return newstr;
  450. }
  451. #endif
  452. //------------------------------------------------------------------------------
  453. //eof