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.

memeory_test.cpp 25KB

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