Open Source Tomb Raider Engine
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.

memory_test.cpp 26KB

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