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 25KB

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