Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

memory_test.cpp 21KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183
  1. /* -*- Mode: C++; tab-width: 3; indent-tabs-mode: t; c-basic-offset: 3 -*- */
  2. /*================================================================
  3. *
  4. * Project : MTK
  5. * Author : Terry 'Mongoose' Hendrix II
  6. * Website : http://www.westga.edu/~stu7440/
  7. * Email : stu7440@westga.edu
  8. * Object : memory_test
  9. * License : No use w/o permission (C) 2002 Mongoose
  10. * Comments: Memory testing tool kit
  11. *
  12. *
  13. * This file was generated using Mongoose's C++
  14. * template generator script. <stu7440@westga.edu>
  15. *
  16. *-- History -------------------------------------------------
  17. *
  18. * 2002.03.27:
  19. * Mongoose - Created
  20. =================================================================*/
  21. #include <string.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #define UNIT_TEST_MEMORY
  25. #include <memory_test.h>
  26. #define USE_ITERATIVE_TREE_INSERT
  27. bool tree_check(rbtree_t *tree, const char *file, int line)
  28. {
  29. bool ret = true;
  30. if (tree)
  31. {
  32. if (tree == tree->parent ||
  33. tree == tree->right ||
  34. tree == tree->left)
  35. {
  36. printf("\nERROR: Self pointing %s:%i\n", file, line);
  37. ret = false;
  38. }
  39. if (tree->parent &&
  40. (tree->parent == tree->left || tree->parent == tree->right))
  41. {
  42. printf("\nERROR: Parent is also child %s:%i\n", file, line);
  43. ret = false;
  44. }
  45. if (tree->left && tree->left == tree->right)
  46. {
  47. printf("\nERROR: Duplicate children %s:%i\n", file, line);
  48. ret = false;
  49. }
  50. }
  51. if (!ret)
  52. {
  53. printf("ERROR: Left %p, Parent %p, Right %p, This %p\a\n",
  54. tree->left, tree->parent, tree->right, tree);
  55. }
  56. return ret;
  57. }
  58. #define CHECK_TREENODE(tree) if (!tree_check(tree, __FILE__, __LINE__)) {exit(0);}
  59. bool check_red_black_tree(rbtree_t *current, bool valid, bool strict)
  60. {
  61. rbtree_t *right, *left;
  62. int color_red;
  63. if (!current)
  64. {
  65. return valid;
  66. }
  67. if (strict)
  68. {
  69. CHECK_TREENODE(current);
  70. }
  71. // Mongoose 2002.02.19, Check for a red root
  72. if (!current->parent && current->color == RB_RED)
  73. {
  74. printf("Invalid root color\n");
  75. return false;
  76. }
  77. color_red = (current->color == RB_RED);
  78. left = current->left;
  79. right = current->right;
  80. // Mongoose 2002.02.19, Check for adj red nodes
  81. if (left)
  82. {
  83. if (color_red && left->color == RB_RED)
  84. {
  85. printf("Invalid adjacent red colors in a left branch, %p\n",
  86. left);
  87. return false;
  88. }
  89. if (!check_red_black_tree(left, valid, strict))
  90. {
  91. return false;
  92. }
  93. }
  94. if (right)
  95. {
  96. if (color_red && right->color == RB_RED)
  97. {
  98. printf("Invalid adjacent red colors in a right branch, %p\n",
  99. right);
  100. return false;
  101. }
  102. if (!check_red_black_tree(right, valid, strict))
  103. {
  104. return false;
  105. }
  106. }
  107. return true;
  108. }
  109. void tree_valid_report(rbtree_t *root)
  110. {
  111. printf("Is valid red-black tree? %s\n",
  112. check_red_black_tree(root, true, true) ? "true" : "false \a");
  113. }
  114. rbtree_t *tree_find(rbtree_t *tree, DWORD key)
  115. {
  116. if (!tree)
  117. return 0;
  118. if (key == tree->key)
  119. {
  120. return tree;
  121. }
  122. else if (tree->left && key < tree->key)
  123. {
  124. return tree_find(tree->left, key);
  125. }
  126. else if (tree->right)
  127. {
  128. return tree_find(tree->right, key);
  129. }
  130. return 0;
  131. }
  132. rbtree_t *tree_new(void *data, DWORD key)
  133. {
  134. rbtree_t *tree;
  135. tree = (rbtree_t *)malloc(sizeof(rbtree_t));
  136. tree->parent = 0;
  137. tree->left = 0;
  138. tree->right = 0;
  139. tree->data = data;
  140. tree->color = RB_RED;
  141. tree->key = key;
  142. return tree;
  143. }
  144. void tree_rotate_left(rbtree_t **root, rbtree_t *tree)
  145. {
  146. rbtree_t *right, *right_leftchild, *uncle;
  147. if (!tree || !(*root))
  148. {
  149. return;
  150. }
  151. // Get tree's right node
  152. right = tree->right;
  153. // Get right node's left child
  154. if (right)
  155. {
  156. right_leftchild = right->left;
  157. }
  158. else
  159. {
  160. right_leftchild = 0;
  161. }
  162. // Set tree's right node to right's left child
  163. tree->right = right_leftchild;
  164. // Child now has a new parent
  165. if (right_leftchild)
  166. {
  167. right_leftchild->parent = tree;
  168. }
  169. // Right also has a new parent
  170. if (right)
  171. {
  172. right->parent = tree->parent;
  173. }
  174. if (tree->parent) // Not root
  175. {
  176. uncle = (tree->parent)->left;
  177. // Mix up at hosptial, switch parent's children!
  178. if (tree == uncle)
  179. {
  180. (tree->parent)->left = right;
  181. }
  182. else
  183. {
  184. (tree->parent)->right = right;
  185. }
  186. }
  187. else // TreeNode 'tree' was root, so now right is root
  188. {
  189. *root = right;
  190. }
  191. if (right)
  192. right->left = tree;
  193. tree->parent = right;
  194. }
  195. void tree_rotate_right(rbtree_t **root, rbtree_t *tree)
  196. {
  197. rbtree_t *left, *left_rightchild, *parent, *uncle;
  198. if (!tree || !(*root))
  199. {
  200. return;
  201. }
  202. left = tree->left;
  203. left_rightchild = 0;
  204. if (left)
  205. {
  206. left_rightchild = left->right;
  207. }
  208. tree->left = left_rightchild;
  209. if (left_rightchild)
  210. {
  211. left_rightchild->parent = tree;
  212. }
  213. if (left)
  214. {
  215. left->parent = tree->parent;
  216. }
  217. parent = tree->parent;
  218. if (parent) //if node is not the root
  219. {
  220. uncle = parent->right;
  221. if (tree == uncle)
  222. {
  223. parent->right = left;
  224. }
  225. else
  226. {
  227. parent->left = left;
  228. }
  229. }
  230. else
  231. {
  232. *root = left;
  233. }
  234. left->right = tree;
  235. tree->parent = left;
  236. }
  237. rbtree_t *tree_insert(rbtree_t **root, void *data, DWORD key)
  238. {
  239. rbtree_t *tree, *prev, *uncle;
  240. // Allocate and store new node in tree ////////
  241. if (!(*root))
  242. {
  243. *root = tree_new(data, key);
  244. (*root)->color = RB_BLACK;
  245. return (*root);
  246. }
  247. tree = *root;
  248. prev = 0x0;
  249. do
  250. {
  251. prev = tree;
  252. if (key < prev->key)
  253. {
  254. tree = prev->left;
  255. }
  256. else if (key > prev->key)
  257. {
  258. tree = prev->right;
  259. }
  260. else // Duplicate
  261. {
  262. return 0x0; // Don't allow duplicates
  263. }
  264. } while (tree);
  265. if (key < prev->key)
  266. {
  267. prev->left = tree_new(data, key);
  268. tree = prev->left;
  269. }
  270. else
  271. {
  272. prev->right = tree_new(data, key);
  273. tree = prev->right;
  274. }
  275. tree->parent = prev;
  276. prev = tree;
  277. // Now do red-black fix for insertion ///////////////////
  278. while ((tree != (*root)) && tree->parent->color == RB_RED)
  279. {
  280. // Parent is a left child
  281. if (tree->parent == tree->parent->parent->left)
  282. {
  283. // Tree's right uncle
  284. uncle = tree->parent->parent->right;
  285. // Parent and Uncle are RED
  286. if ((uncle) && (uncle->color == RB_RED))
  287. {
  288. // Change Parent and Uncle to BLACK, make grandparent RED
  289. tree->parent->color = RB_BLACK;
  290. uncle->color = RB_BLACK;
  291. tree->parent->parent->color = RB_RED;
  292. // Continue from grandparent
  293. tree = tree->parent->parent;
  294. }
  295. else // Parent is RED and Uncle is BLACK
  296. {
  297. // Tree is a right child
  298. if (tree == tree->parent->right)
  299. {
  300. tree_rotate_left(root, tree->parent);
  301. tree = tree->left;
  302. }
  303. tree->parent->color = RB_BLACK;
  304. tree->parent->parent->color = RB_RED;
  305. tree_rotate_right(root, tree->parent->parent);
  306. }
  307. }
  308. else // Parent is a right child
  309. {
  310. // Tree's left uncle
  311. uncle = tree->parent->parent->left;
  312. // Parent and Uncle are RED
  313. if ((uncle) && (uncle->color == RB_RED))
  314. {
  315. // Change Parent and Uncle to BLACK, make grandparent RED
  316. tree->parent->color = RB_BLACK;
  317. uncle->color = RB_BLACK;
  318. tree->parent->parent->color = RB_RED;
  319. // Continue from grandparent
  320. tree = tree->parent->parent;
  321. }
  322. else // Parent is RED and Uncle is BLACK
  323. {
  324. // Tree is a left child
  325. if (tree == tree->parent->left)
  326. {
  327. tree_rotate_right(root, tree->parent);
  328. tree = tree->right;
  329. }
  330. tree->parent->color = RB_BLACK;
  331. tree->parent->parent->color = RB_RED;
  332. tree_rotate_left(root, tree->parent->parent);
  333. }
  334. }
  335. }
  336. (*root)->color = RB_BLACK;
  337. return prev;
  338. }
  339. int tree_print(rbtree_t *tree, void (*print_func)(void *))
  340. {
  341. int i = 0;
  342. if (!tree)
  343. return 0;
  344. if (tree->left)
  345. {
  346. i += tree_print(tree->left, print_func);
  347. printf(",\n");
  348. }
  349. if (tree->data && print_func)
  350. {
  351. (*print_func)(tree->data);
  352. #ifdef DEBUG_MEMORY_RBTREE
  353. printf(" :%s%s)",
  354. (!tree->parent) ? " (root, " : " ("),
  355. (tree->color == RB_BLACK) ? "black" : "red");
  356. #endif
  357. }
  358. ++i;
  359. if (tree->right)
  360. {
  361. printf(",\n");
  362. i += tree_print(tree->right, print_func);
  363. }
  364. if (!tree->parent)
  365. {
  366. printf("\n%i nodes, %lu bytes each : %lu bytes\n",
  367. i, sizeof(rbtree_t), i * sizeof(rbtree_t));
  368. }
  369. return i;
  370. }
  371. rbtree_t *tree_get_successor(rbtree_t *root, rbtree_t *tree)
  372. {
  373. rbtree_t *successor;
  374. successor = tree->right;
  375. if (successor)
  376. {
  377. while (successor->left)
  378. {
  379. successor = successor->left;
  380. }
  381. return successor;
  382. }
  383. else
  384. {
  385. successor = tree->parent;
  386. while (tree == successor->right)
  387. {
  388. tree = successor;
  389. successor = successor->parent;
  390. }
  391. if (successor == root)
  392. {
  393. return 0;
  394. }
  395. return successor;
  396. }
  397. }
  398. rbtree_t *tree_get_predecessor(rbtree_t *root,rbtree_t *tree)
  399. {
  400. rbtree_t *predecessor;
  401. predecessor = tree->left;
  402. if (predecessor)
  403. {
  404. while (predecessor->right)
  405. {
  406. predecessor = predecessor->right;
  407. }
  408. return predecessor;
  409. }
  410. else
  411. {
  412. predecessor = tree->parent;
  413. while (tree == predecessor->left)
  414. {
  415. if (predecessor == root)
  416. {
  417. return 0;
  418. }
  419. tree = predecessor;
  420. predecessor = predecessor->parent;
  421. }
  422. return predecessor;
  423. }
  424. }
  425. void tree_restore_after_remove(rbtree_t **root, rbtree_t *tree)
  426. {
  427. rbtree_t *parent, *sibling, *sleft, *sright;
  428. if (!tree || !(*root))
  429. {
  430. return;
  431. }
  432. parent = tree->parent;
  433. while ((tree != (*root)) && (tree->color == RB_BLACK)) // was parent->color
  434. {
  435. if (tree == parent->left)
  436. {
  437. sibling = parent->right;
  438. if (sibling && sibling->color == RB_RED)
  439. {
  440. sibling->color = RB_BLACK;
  441. parent->color = RB_RED;
  442. tree_rotate_left(root, tree->parent);
  443. parent = tree->parent;
  444. sibling = parent->right;
  445. }
  446. if (sibling)
  447. {
  448. sleft = sibling->left;
  449. sright = sibling->right;
  450. }
  451. else
  452. {
  453. sleft = sright = NULL;
  454. }
  455. if ((!sright || sright->color == RB_BLACK) &&
  456. (!sleft || sleft->color == RB_BLACK))
  457. {
  458. if (sibling)
  459. sibling->color = RB_RED;
  460. tree = parent;
  461. }
  462. else
  463. {
  464. if (!sright || sright->color == RB_BLACK)
  465. {
  466. sibling->color = RB_RED;
  467. sleft->color = RB_BLACK;
  468. tree_rotate_right(root, sibling);
  469. sibling = parent->right;
  470. sright = sibling->right;
  471. sleft = sibling->left;
  472. }
  473. sibling->color = parent->color;
  474. parent->color = RB_BLACK;
  475. sright->color = RB_BLACK;
  476. tree_rotate_left(root, tree->parent);
  477. parent = tree->parent;
  478. tree = (*root);
  479. }
  480. }
  481. else
  482. {
  483. sibling = parent->left;
  484. if (sibling && sibling->color == RB_RED)
  485. {
  486. sibling->color = RB_BLACK;
  487. parent->color = RB_RED;
  488. tree_rotate_right(root, tree->parent);
  489. parent = tree->parent;
  490. sibling = parent->left;
  491. }
  492. if (sibling)
  493. {
  494. sleft = sibling->left;
  495. sright = sibling->right;
  496. }
  497. else
  498. {
  499. sleft = sright = 0;
  500. }
  501. if ((!sright || sright->color == RB_BLACK) &&
  502. (!sleft || sleft->color == RB_BLACK))
  503. {
  504. if (sibling)
  505. sibling->color = RB_RED;
  506. tree = parent;
  507. }
  508. else
  509. {
  510. if (!sleft || sleft->color == RB_BLACK)
  511. {
  512. sibling->color = RB_RED;
  513. sright->color = RB_BLACK;
  514. tree_rotate_left(root, sibling);
  515. sibling = parent->left;
  516. }
  517. sibling->color = parent->color;
  518. parent->color = RB_BLACK;
  519. if (sleft) sleft->color = RB_BLACK;
  520. tree_rotate_right(root, tree->parent);
  521. parent = tree->parent;
  522. tree = (*root);
  523. }
  524. }
  525. parent = tree->parent;
  526. }
  527. tree->color = RB_BLACK;
  528. }
  529. void tree_remove(rbtree_t **root, rbtree_t *tree)
  530. {
  531. rbtree_t *left, *right, *parent, *prev, *cur;
  532. // Mongoose 2002.02.16, Nothing to remove
  533. if (!tree || !(*root))
  534. {
  535. return;
  536. }
  537. left = tree->left;
  538. right = tree->right;
  539. parent = tree->parent;
  540. if (!left || !right)
  541. {
  542. prev = tree;
  543. }
  544. else
  545. {
  546. prev = tree_get_successor((*root), tree);
  547. }
  548. if (prev->left)
  549. {
  550. cur = prev->left;
  551. }
  552. else
  553. {
  554. cur = prev->right;
  555. }
  556. if (cur)
  557. {
  558. cur->parent = prev->parent;
  559. }
  560. if (!prev->parent)
  561. {
  562. *root = cur;
  563. }
  564. else
  565. {
  566. parent = prev->parent;
  567. if (prev == parent->left)
  568. {
  569. parent->left = cur;
  570. }
  571. else
  572. {
  573. parent->right = cur;
  574. }
  575. }
  576. if (prev != tree)
  577. {
  578. tree->data = prev->data;
  579. tree->key = prev->key;
  580. }
  581. if (prev->color == RB_BLACK)
  582. {
  583. tree_restore_after_remove(root, cur);
  584. }
  585. free(prev);
  586. }
  587. #ifdef DEBUG_MEMORY
  588. typedef struct meminfo_s
  589. {
  590. DWORD address;
  591. DWORD size;
  592. unsigned short int line;
  593. meminfo_filename_t *filename;
  594. } meminfo_t;
  595. void __print_dword(DWORD d)
  596. {
  597. printf("0x%08lx", d);
  598. }
  599. void __print_meminfo(meminfo_t *meminfo)
  600. {
  601. if (meminfo)
  602. {
  603. printf("<addr 0x%08lx, sz %lu, \"%s\":%u>",
  604. meminfo->address,
  605. meminfo->size,
  606. (!meminfo->filename) ? "?" : meminfo->filename->filename,
  607. meminfo->line);
  608. }
  609. }
  610. ///////////////////////////////////////////////////////////////////
  611. ///////////////////////////////////////////////////////////////////
  612. rbtree_t *MEMORY_INFO = 0;
  613. meminfo_filename_t *MEMORY_FILENAME = 0;
  614. long MEMORY_USED = 0L;
  615. long MEMORYA_USED = 0L;
  616. long MEMORYC_USED = 0L;
  617. long MAX_MEMORY_USED = 0L;
  618. long MAX_MEMORYA_USED = 0L;
  619. long MAX_MEMORYC_USED = 0L;
  620. typedef enum
  621. {
  622. MEMORY_USED_BY_PROGRAM = 1,
  623. MEMORY_USED_BY_OVERHEAD = 2,
  624. MEMORY_USED_TOTAL = 3,
  625. MAX_MEMORY_USED_BY_PROGRAM = 4,
  626. MAX_MEMORY_USED_BY_OVERHEAD = 5
  627. } memory_query_t;
  628. long memory_used(memory_query_t query)
  629. {
  630. switch (query)
  631. {
  632. case MEMORY_USED_BY_PROGRAM:
  633. return MEMORY_USED;
  634. break;
  635. case MAX_MEMORY_USED_BY_PROGRAM:
  636. return MAX_MEMORY_USED;
  637. break;
  638. case MAX_MEMORY_USED_BY_OVERHEAD:
  639. return MAX_MEMORYA_USED + MAX_MEMORYC_USED;
  640. break;
  641. case MEMORY_USED_BY_OVERHEAD:
  642. return MEMORYA_USED + MEMORYC_USED;
  643. break;
  644. case MEMORY_USED_TOTAL:
  645. return MEMORY_USED + MEMORYA_USED + MEMORYC_USED;
  646. break;
  647. default:
  648. ;
  649. }
  650. return 0;
  651. }
  652. void display_memory_usage()
  653. {
  654. unsigned int i;
  655. meminfo_filename_t *cur = MEMORY_FILENAME;
  656. printf("\n============================================================\n");
  657. printf("Memory usage per file:\n");
  658. while (cur)
  659. {
  660. printf(" %s : ( %lu bytes, %3.2f%% )\n",
  661. cur->filename, cur->size,
  662. 100.0 * ((float)cur->size / (float)MEMORY_USED));
  663. cur = cur->next;
  664. }
  665. printf("------------------------------------------------------------\n");
  666. cur = MEMORY_FILENAME;
  667. printf("Memory special errors per file:\n");
  668. while (cur)
  669. {
  670. if (cur->alloc_zero)
  671. {
  672. printf(" %s : %u zero allocation errors\n",
  673. cur->filename, cur->alloc_zero);
  674. printf(" lines:");
  675. for (i = 0; i < ZERO_ALLOC_SLOTS; ++i)
  676. {
  677. if (cur->alloc_zero_at_line[i])
  678. {
  679. printf(" %u",
  680. cur->alloc_zero_at_line[i]);
  681. break;
  682. }
  683. }
  684. printf("\n");
  685. }
  686. cur = cur->next;
  687. }
  688. printf("------------------------------------------------------------\n");
  689. printf("Memory usage summary:\n");
  690. printf(" Tracked program memory : %lu bytes \t(%.2f MB)\n",
  691. MEMORY_USED, (double)MEMORY_USED / 1024000.0);
  692. printf(" Untracked overhead memory : %lu bytes \t(%.2f MB)\n",
  693. MEMORYA_USED, (double)MEMORYA_USED / 1024000.0);
  694. printf(" Untracked m-string memory : %lu bytes\n",
  695. MEMORYC_USED);
  696. printf("\n Total accounted memory : %lu bytes \t(%.2f MB)\n",
  697. MEMORY_USED + MEMORYA_USED + MEMORYC_USED,
  698. (double)(MEMORY_USED + MEMORYA_USED + MEMORYC_USED) / 1024000.0);
  699. printf("------------------------------------------------------------\n");
  700. printf("Memory max usage summary:\n");
  701. printf(" Tracked program memory : %lu bytes \t(%.2f MB)\n",
  702. MAX_MEMORY_USED, (double)MAX_MEMORY_USED / 1024000.0);
  703. printf(" Untracked overhead memory : %lu bytes \t(%.2f MB)\n",
  704. MAX_MEMORYA_USED, (double)MAX_MEMORYA_USED / 1024000.0);
  705. printf(" Untracked m-string memory : %lu bytes\n",
  706. MAX_MEMORYC_USED);
  707. printf("\n Total accounted memory : %lu bytes \t(%.2f MB)\n",
  708. MAX_MEMORY_USED + MAX_MEMORYA_USED + MAX_MEMORYC_USED,
  709. (double)(MAX_MEMORY_USED + MAX_MEMORYA_USED + MAX_MEMORYC_USED) / 1024000.0);
  710. printf("============================================================\n");
  711. }
  712. void dump_memory_report()
  713. {
  714. int i;
  715. printf("\n============================================================\n");
  716. printf(" Memory status report\n");
  717. printf("============================================================\n");
  718. printf("Memory tracking table:\n");
  719. i = tree_print(MEMORY_INFO, (void (*)(void *))&__print_meminfo);
  720. printf("%i records, %lu bytes each : %lu bytes\n",
  721. i, sizeof(meminfo_t), i * sizeof(meminfo_t));
  722. display_memory_usage();
  723. printf("============================================================\n\n");
  724. }
  725. void delete_check(const char *file, int line, int print);
  726. ///////////////////////////////////////////////////////////////////
  727. ///////////////////////////////////////////////////////////////////
  728. void add_track(DWORD addr, DWORD size, const char *filename, DWORD line_num)
  729. {
  730. meminfo_filename_t *memfile, *memfile_prev;
  731. meminfo_t *meminfo;
  732. unsigned int len, i;
  733. MEMORY_USED += size;
  734. if (MEMORY_USED > MAX_MEMORY_USED)
  735. {
  736. MAX_MEMORY_USED = MEMORY_USED;
  737. }
  738. MEMORYA_USED += sizeof(meminfo_t);
  739. if (MEMORYA_USED > MAX_MEMORYA_USED)
  740. {
  741. MAX_MEMORYA_USED = MEMORYA_USED;
  742. }
  743. meminfo = (meminfo_t *)malloc(sizeof(meminfo_t));
  744. meminfo->address = addr;
  745. meminfo->line = line_num;
  746. meminfo->size = size;
  747. meminfo->filename = 0;
  748. if (size == 0)
  749. {
  750. printf("\nERROR: %s:%lu Allocated 0 bytes\n", filename, line_num);
  751. }
  752. if (filename || filename[0])
  753. {
  754. len = strlen(filename);
  755. memfile = memfile_prev = 0;
  756. if (MEMORY_FILENAME)
  757. {
  758. memfile = MEMORY_FILENAME;
  759. while (memfile)
  760. {
  761. if (strncmp(filename, memfile->filename, len) == 0)
  762. break;
  763. memfile_prev = memfile;
  764. memfile = memfile->next;
  765. }
  766. }
  767. if (!memfile)
  768. {
  769. memfile = (meminfo_filename_t *)malloc(sizeof(meminfo_filename_t));
  770. memfile->filename_len = len;
  771. memfile->filename = (char *)malloc(len+1);
  772. strncpy(memfile->filename, filename, len);
  773. memfile->filename[len+1] = 0;
  774. memfile->next = 0;
  775. memfile->size = 0;
  776. memfile->alloc_zero = 0;
  777. memfile->alloc_zero_at_line[0] = 0;
  778. memfile->alloc_zero_at_line[1] = 0;
  779. memfile->alloc_zero_at_line[2] = 0;
  780. MEMORYC_USED += sizeof(meminfo_filename_t) + memfile->filename_len;
  781. if (MEMORYC_USED > MAX_MEMORYC_USED)
  782. MAX_MEMORYC_USED = MEMORYC_USED;
  783. if (memfile_prev)
  784. {
  785. memfile_prev->next = memfile;
  786. }
  787. if (!MEMORY_FILENAME)
  788. {
  789. MEMORY_FILENAME = memfile;
  790. }
  791. }
  792. meminfo->filename = memfile;
  793. if (memfile)
  794. {
  795. if (meminfo->size == 0)
  796. {
  797. memfile->alloc_zero += 1;
  798. for (i = 0; i < ZERO_ALLOC_SLOTS; ++i)
  799. {
  800. if (memfile->alloc_zero_at_line[i] == line_num)
  801. break;
  802. if (!memfile->alloc_zero_at_line[i])
  803. {
  804. memfile->alloc_zero_at_line[i] = line_num;
  805. break;
  806. }
  807. }
  808. }
  809. memfile->size += meminfo->size;
  810. }
  811. }
  812. MEMORYA_USED += sizeof(rbtree_t);
  813. tree_insert(&MEMORY_INFO, meminfo, meminfo->address);
  814. #ifdef DEBUG_MEMORY_VERBOSE
  815. printf("add_track> addr 0x%08lx, size %lu, filename %s, line %lu\n",
  816. addr, size, filename, line_num);
  817. #endif
  818. }
  819. /////////////////////////////////////////////////////////////////
  820. void remove_track(DWORD addr)
  821. {
  822. meminfo_t *meminfo = 0;
  823. rbtree_t *tree = 0;
  824. tree = tree_find(MEMORY_INFO, addr);
  825. if (tree)
  826. {
  827. meminfo = (meminfo_t *)tree->data;
  828. if (meminfo)
  829. {
  830. tree_remove(&MEMORY_INFO, tree);
  831. if (meminfo->filename)
  832. {
  833. meminfo->filename->size -= meminfo->size;
  834. }
  835. if (meminfo->size == 0)
  836. {
  837. printf("\nERROR: %s:%u Deallocated 0 bytes\n",
  838. (meminfo->filename) ? meminfo->filename->filename : "?",
  839. meminfo->line);
  840. }
  841. MEMORY_USED -= meminfo->size;
  842. MEMORYA_USED -= sizeof(meminfo_t);
  843. MEMORYA_USED -= sizeof(rbtree_t);
  844. free(meminfo);
  845. }
  846. }
  847. else
  848. {
  849. #ifndef DEBUG_MEMORY_ERROR_OFF
  850. printf("\nERROR: remove_track> Unknown addr 0x%08lx ", addr);
  851. delete_check(0, 0, 1);
  852. printf("?\n");
  853. #endif
  854. }
  855. if (!MEMORY_INFO)
  856. {
  857. meminfo_filename_t *cur;
  858. meminfo_filename_t *del;
  859. cur = MEMORY_FILENAME;
  860. MEMORY_FILENAME = 0;
  861. while (cur)
  862. {
  863. del = cur;
  864. cur = cur->next;
  865. MEMORYC_USED -= sizeof(meminfo_filename_t);
  866. if (del->filename)
  867. {
  868. MEMORYC_USED -= del->filename_len;
  869. free(del->filename);
  870. }
  871. free(del);
  872. }
  873. }
  874. #ifdef DEBUG_MEMORY_VERBOSE
  875. printf("remove_track> addr 0x%lx\n", addr);
  876. #endif
  877. }
  878. //////////////////////////////////////////////////////////////////////
  879. //////////////////////////////////////////////////////////////////////
  880. void *operator new(size_t size, const char *file, int line)
  881. {
  882. void *ptr = (void *)malloc(size);
  883. add_track((DWORD)ptr, size, file, line);
  884. return ptr;
  885. }
  886. void *operator new [](size_t size, const char *file, int line)
  887. {
  888. void *ptr = (void *)malloc(size);
  889. add_track((DWORD)ptr, size, file, line);
  890. return ptr;
  891. }
  892. // Mongoose 2002.03.29, Prob should reduce this with meminfo_filename use
  893. void delete_check(const char *file, int line, int print)
  894. {
  895. static char s[64];
  896. static int l;
  897. unsigned int len;
  898. if (!print)
  899. {
  900. l = line;
  901. if (!file || !file[0])
  902. {
  903. s[0] = 0;
  904. return;
  905. }
  906. len = strlen(file);
  907. if (len > 63)
  908. len = 63;
  909. strncpy(s, file, len);
  910. s[len] = 0;
  911. }
  912. else
  913. {
  914. printf("%s:%i", s, l);
  915. }
  916. }
  917. void operator delete(void *p)
  918. {
  919. remove_track((DWORD)p);
  920. free(p);
  921. }
  922. void operator delete [](void *p)
  923. {
  924. remove_track((DWORD)p);
  925. free(p);
  926. }
  927. #endif