dpmem.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. /*
  2. * Copyright 2021
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * These are the four essential freedoms with GNU GPL software:
  18. * 1: freedom to run the program, for any purpose
  19. * 2: freedom to study how the program works, and change it to make it do what you wish
  20. * 3: freedom to redistribute copies to help your Free Software friends
  21. * 4: freedom to distribute copies of your modified versions to your Free Software friends
  22. * , ,
  23. * / \
  24. * ((__-^^-,-^^-__))
  25. * `-_---' `---_-'
  26. * `--|o` 'o|--'
  27. * \ ` /
  28. * ): :(
  29. * :o_o:
  30. * "-"
  31. *
  32. * SPDX-License-Identifier: GPL-3.0+
  33. * License-Filename: LICENSE
  34. */
  35. /* wrappers for malloc/calloc/realloc/free
  36. * when there is no more memory no crash
  37. * but a message and call to exit()
  38. * malloc is redirected to calloc.
  39. *
  40. * This is needed because gcc-11 -fanalyzer option generates warnings at every
  41. * malloc/callon in the source but wrapping it this way stops these messages.
  42. * This program does many small malloc() and few bigger. glibc malloc can handle that.
  43. */
  44. #include "config.h"
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. /* switch mem lib */
  49. #define CLIB 1 /* for testing plain clib is easier */
  50. #ifdef CLIB
  51. /* use the c lib */
  52. #else
  53. /* use gtk lib */
  54. #include <gtk/gtk.h>
  55. #endif
  56. #include "splay-tree.h"
  57. #include "main.h"
  58. #include "dp.h"
  59. #include "dpmem.h"
  60. static splay_tree memdata = NULL;
  61. static void memcheck_free(void *ptr);
  62. static void *memcheck_calloc(size_t nmemb, size_t size);
  63. static void *memcheck_realloc(void *ptr, size_t size);
  64. /* wrapper for free()
  65. * This always returns (void *)0
  66. * This is used to set pointers to zero automatically
  67. * p = dp_free (p);
  68. * This can prevent hidden bugs
  69. * This may help checking software as valgrind and more
  70. * This can be extended to clear free'ed memory before free() to make it even more safe
  71. * But here only calloc() is used then random dat is no problem
  72. * clang scan-build will generate there warnings
  73. * warning: Value stored to 'fptr' is never read
  74. * fptr = dp_free(fptr);
  75. * ^~~~~~~~~~~~~~
  76. * This is true and can be ignored
  77. * then (void)dp_free(p) cn be used
  78. * or adding: (void)p;
  79. * or adding: if(p){}
  80. * or adding: compiler specific pragma
  81. * or adding: compiler specific attribute
  82. */
  83. void *dp_free(void *ptr)
  84. {
  85. char *p = NULL;
  86. if (ptr) {
  87. memcheck_free(ptr);
  88. } else {
  89. printf("%s(): nil ptr\n", __func__);
  90. if (0) {
  91. /* this is a segv to use with gdb then bt command where it came from. */
  92. *p = 1;
  93. }
  94. }
  95. return ((void *)0);
  96. }
  97. /* */
  98. void *dp_malloc(size_t n)
  99. {
  100. /* malloc() does not happen in gml4gtk but in the bison parser code. */
  101. if (n == 0) {
  102. printf("%s(): 0 malloc\n", __func__);
  103. }
  104. return (dp_calloc(1, n));
  105. }
  106. /* */
  107. void *dp_calloc(size_t nmemb, size_t size)
  108. {
  109. void *ret = NULL;
  110. if ((nmemb * size) == 0) {
  111. /* shouldnothappen */
  112. printf("%s(): nmemb=%d, size=%d 0 bytes\n", __func__, (int)nmemb, (int)size);
  113. }
  114. ret = memcheck_calloc(nmemb, size);
  115. if (ret == NULL) {
  116. printf("%s(): no memory\n", __func__);
  117. exit(1);
  118. }
  119. return (ret);
  120. }
  121. /* */
  122. void *dp_realloc(void *ptr, size_t n)
  123. {
  124. void *ret = NULL;
  125. /* realloc() does not happen in gml4gtk but in the bison parser code. */
  126. ret = memcheck_realloc(ptr, n);
  127. /* with size 0, return NULL is oke. */
  128. if (n) {
  129. if (ret == NULL) {
  130. printf("%s(): nil realloc\n", __func__);
  131. exit(1);
  132. }
  133. }
  134. return (ret);
  135. }
  136. #ifdef MEMCHECK
  137. /* extra memory checking */
  138. /* A splay-tree datatype.
  139. Copyright (C) 1998-2021 Free Software Foundation, Inc.
  140. Contributed by Mark Mitchell (mark@markmitchell.com).
  141. This file is part of GNU CC.
  142. GNU CC is free software; you can redistribute it and/or modify it
  143. under the terms of the GNU General Public License as published by
  144. the Free Software Foundation; either version 2, or (at your option)
  145. any later version.
  146. GNU CC is distributed in the hope that it will be useful, but
  147. WITHOUT ANY WARRANTY; without even the implied warranty of
  148. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  149. General Public License for more details.
  150. You should have received a copy of the GNU General Public License
  151. along with GNU CC; see the file COPYING. If not, write to
  152. the Free Software Foundation, 51 Franklin Street - Fifth Floor,
  153. Boston, MA 02110-1301, USA. */
  154. /* For an easily readable description of splay-trees, see:
  155. Lewis, Harry R. and Denenberg, Larry. Data Structures and Their
  156. Algorithms. Harper-Collins, Inc. 1991. */
  157. /* custom splay() using calloc/free */
  158. /* splay routines */
  159. static splay_tree m_splay_tree_new(splay_tree_compare_fn fnc, splay_tree_delete_key_fn fndk, splay_tree_delete_value_fn fndv);
  160. static splay_tree m_splay_tree_delete(splay_tree sp);
  161. static void m_splay_tree_insert(splay_tree sp, splay_tree_key k, splay_tree_value v);
  162. static void m_splay_tree_remove(splay_tree sp, splay_tree_key key);
  163. static splay_tree_node m_splay_tree_lookup(splay_tree sp, splay_tree_key k);
  164. static splay_tree_node m_splay_tree_min(splay_tree sp);
  165. /* Return the immediate successor KEY, or NULL if there is no
  166. successor. KEY need not be present in the tree. */
  167. static splay_tree_node m_splay_tree_successor(splay_tree sp, splay_tree_key key);
  168. /* return 1 if splay tree has data, otherwise 0 */
  169. static int m_splay_tree_has_data(splay_tree sp);
  170. /* free() wrappers to free key/value */
  171. static void m_splay_tree_free_key(splay_tree_key key);
  172. static int m_splay_tree_compare_pointers(splay_tree_key k1, splay_tree_key k2);
  173. /* forward decl. */
  174. static struct splay_tree_node_n *m_splay(splay_tree sp, splay_tree_key key);
  175. /* delete whole sp tree */
  176. static splay_tree m_splay_tree_delete(splay_tree sp)
  177. {
  178. splay_tree_node spn = (splay_tree_node) 0;
  179. splay_tree_key *keys = (splay_tree_key *) 0;
  180. int count = 0;
  181. int i = 0;
  182. if (sp == (splay_tree) 0) {
  183. return ((splay_tree) 0);
  184. }
  185. /* if there is data */
  186. if (sp->root) {
  187. /* for every node, this can not cause stack smashing.
  188. * this is slowest way possible but splay_tree_delete() does almost never happen.
  189. * gcc realloc()'s array with pointers to free() but using realloc()
  190. * may cause unexpected high memory usage, thats why avoiding realloc() use.
  191. */
  192. spn = m_splay_tree_min(sp);
  193. while (spn) {
  194. count++;
  195. spn = m_splay_tree_successor(sp, spn->key);
  196. }
  197. count++;
  198. keys = calloc(1, (count * sizeof(splay_tree_key)));
  199. if (keys) {
  200. spn = m_splay_tree_min(sp);
  201. i = 0;
  202. while (spn) {
  203. keys[i] = (splay_tree_key) spn->key;
  204. i++;
  205. spn = m_splay_tree_successor(sp, spn->key);
  206. }
  207. for (i = 0; i < count; i++) {
  208. m_splay_tree_remove(sp, (splay_tree_key) keys[i]);
  209. keys[i] = (splay_tree_key) 0;
  210. }
  211. free(keys);
  212. }
  213. }
  214. /* wipe the pointers in the struct to make valgrind happy */
  215. sp->root = (splay_tree_node) 0;
  216. /* The comparision function. */
  217. sp->comp = (splay_tree_compare_fn) 0;
  218. /* The deallocate-key function. NULL if no cleanup is necessary. */
  219. sp->delete_key = (splay_tree_delete_key_fn) 0;
  220. /* The deallocate-value function. NULL if no cleanup is necessary. */
  221. sp->delete_value = (splay_tree_delete_value_fn) 0;
  222. free((void *)sp);
  223. return ((splay_tree) 0);
  224. }
  225. /* Allocate a new splay tree, using COMPARE_FN to compare nodes,
  226. DELETE_KEY_FN to deallocate keys, and DELETE_VALUE_FN to deallocate
  227. values. */
  228. static splay_tree
  229. m_splay_tree_new(splay_tree_compare_fn compare_fn, splay_tree_delete_key_fn delete_key_fn,
  230. splay_tree_delete_value_fn delete_value_fn)
  231. {
  232. splay_tree sp = (splay_tree) 0;
  233. /* there must be a compare function, the free() functions are optional */
  234. if (compare_fn == (splay_tree_compare_fn) 0) {
  235. return ((splay_tree) 0);
  236. }
  237. sp = (splay_tree) calloc(1, sizeof(struct splay_tree_t));
  238. if (sp == (splay_tree) 0) {
  239. return ((splay_tree) 0);
  240. }
  241. /* set root node to use and the functions */
  242. sp->root = (splay_tree_node) 0;
  243. sp->comp = compare_fn;
  244. sp->delete_key = delete_key_fn;
  245. sp->delete_value = delete_value_fn;
  246. return ((splay_tree) sp);
  247. }
  248. /* Insert a new node (associating KEY with DATA) into SP. If a
  249. previous node with the indicated KEY exists, its data is not replaced
  250. with the new value. */
  251. static void m_splay_tree_insert(splay_tree sp, splay_tree_key key, splay_tree_value value)
  252. {
  253. splay_tree_node spn = (splay_tree_node) 0;
  254. int comparison = 0;
  255. if (sp == (splay_tree) 0) {
  256. /* no tree */
  257. return;
  258. }
  259. spn = m_splay_tree_lookup(sp, key);
  260. if (spn != (splay_tree_node) 0) {
  261. /* did already exist */
  262. return;
  263. }
  264. /* Create a new node, and insert it at the root. */
  265. spn = (splay_tree_node) calloc(1, sizeof(struct splay_tree_node_n));
  266. if (spn == (splay_tree_node) 0) {
  267. /* shouldnothappen */
  268. return;
  269. }
  270. /* set node data */
  271. spn->key = key;
  272. spn->value = value;
  273. if (sp->root == (splay_tree_node) 0) {
  274. /* first entry */
  275. sp->root = spn;
  276. return;
  277. }
  278. /* add in tree */
  279. comparison = (*sp->comp) (sp->root->key, key);
  280. if (comparison < 0) {
  281. spn->left = sp->root;
  282. spn->right = spn->left->right;
  283. spn->left->right = (splay_tree_node) 0;
  284. } else {
  285. /* > or == */
  286. spn->right = sp->root;
  287. spn->left = spn->right->left;
  288. spn->right->left = (splay_tree_node) 0;
  289. }
  290. sp->root = spn;
  291. return;
  292. }
  293. /* Remove KEY from SP. It is not an error if it did not exist. */
  294. static void m_splay_tree_remove(splay_tree sp, splay_tree_key key)
  295. {
  296. splay_tree_node spn = (splay_tree_node) 0;
  297. splay_tree_node node = (splay_tree_node) 0;
  298. splay_tree_node left = (splay_tree_node) 0;
  299. splay_tree_node right = (splay_tree_node) 0;
  300. if (sp == (splay_tree) 0) {
  301. /* no tree */
  302. return;
  303. }
  304. if (sp->root == (splay_tree_node) 0) {
  305. /* no data */
  306. return;
  307. }
  308. spn = m_splay_tree_lookup(sp, key);
  309. if (spn == (splay_tree_node) 0) {
  310. return;
  311. }
  312. /* found entry to delete now in spn */
  313. node = sp->root;
  314. left = sp->root->left;
  315. right = sp->root->right;
  316. /* One of the children is now the root. Doesn't matter much
  317. which, so long as we preserve the properties of the tree. */
  318. if (left) {
  319. sp->root = left;
  320. /* If there was a right child as well, hang it off the
  321. right-most leaf of the left child. */
  322. if (right) {
  323. while (left->right) {
  324. left = left->right;
  325. }
  326. left->right = right;
  327. }
  328. } else {
  329. sp->root = right;
  330. }
  331. /* free() key if needed */
  332. if (sp->delete_key) {
  333. /* avoid free(0) */
  334. if (node->key) {
  335. (*sp->delete_key) (node->key);
  336. }
  337. node->key = (splay_tree_key) 0;
  338. }
  339. /* free() value if needed */
  340. if (sp->delete_value) {
  341. /* avoid free(0) */
  342. if (node->value) {
  343. (*sp->delete_value) (node->value);
  344. }
  345. node->value = (splay_tree_value) 0;
  346. }
  347. /* free() node itself and wipe the pointers */
  348. node->left = (splay_tree_node) 0;
  349. node->right = (splay_tree_node) 0;
  350. free((void *)node);
  351. return;
  352. }
  353. /* Lookup KEY in SP, returning VALUE if present, and NULL
  354. otherwise. */
  355. static splay_tree_node m_splay_tree_lookup(splay_tree sp, splay_tree_key key)
  356. {
  357. splay_tree_node spn = (splay_tree_node) 0;
  358. if (sp == (splay_tree) 0) {
  359. /* no tree */
  360. return ((splay_tree_node) 0);
  361. }
  362. if (sp->root == (splay_tree_node) 0) {
  363. /* no data */
  364. return ((splay_tree_node) 0);
  365. }
  366. if ((*sp->comp) (sp->root->key, key) == 0) {
  367. /* found */
  368. return ((splay_tree_node) sp->root);
  369. }
  370. spn = m_splay(sp, key);
  371. if (spn) {
  372. if ((*sp->comp) (sp->root->key, key) == 0) {
  373. /* found */
  374. return ((splay_tree_node) sp->root);
  375. }
  376. }
  377. /* not found */
  378. return ((splay_tree_node) 0);
  379. }
  380. /* Return the node in SP with the smallest key. */
  381. static splay_tree_node m_splay_tree_min(splay_tree sp)
  382. {
  383. splay_tree_node n = (splay_tree_node) 0;
  384. /* <nil> splaytree */
  385. if (sp == (splay_tree) 0) {
  386. return ((splay_tree_node) 0);
  387. }
  388. /* no data */
  389. if (sp->root == (splay_tree_node) 0) {
  390. return ((splay_tree_node) 0);
  391. }
  392. n = sp->root;
  393. /* scan l */
  394. while (n->left) {
  395. n = n->left;
  396. }
  397. return ((splay_tree_node) n);
  398. }
  399. /* return 1 if splay tree has data, otherwise 0 */
  400. static int m_splay_tree_has_data(splay_tree sp)
  401. {
  402. if (sp == (splay_tree) 0) {
  403. return (0);
  404. }
  405. if (sp->root) {
  406. return (1);
  407. } else {
  408. return (0);
  409. }
  410. }
  411. /* Return the immediate successor KEY, or NULL if there is no
  412. successor. KEY need not be present in the tree. */
  413. static splay_tree_node m_splay_tree_successor(splay_tree sp, splay_tree_key key)
  414. {
  415. int comparison = 0;
  416. splay_tree_node node = (splay_tree_node) 0;
  417. if (sp == (splay_tree) 0) {
  418. /* no tree */
  419. return ((splay_tree_node) 0);
  420. }
  421. /* If the tree is empty, there is certainly no successor. */
  422. if (sp->root == (splay_tree_node) 0) {
  423. return ((splay_tree_node) 0);
  424. }
  425. /* Splay the tree around KEY. That will leave either the KEY
  426. itself, its predecessor, or its successor at the root. */
  427. node = m_splay(sp, key);
  428. if (node == (splay_tree_node) 0) {
  429. return ((splay_tree_node) 0);
  430. }
  431. /* */
  432. comparison = (*sp->comp) (sp->root->key, key);
  433. /* If the successor is at the root, just return it. */
  434. if (comparison > 0) {
  435. return ((splay_tree_node) sp->root);
  436. }
  437. /* Otherwise, find the leftmost element of the right subtree. */
  438. node = sp->root->right;
  439. if (node) {
  440. while (node->left) {
  441. node = node->left;
  442. }
  443. }
  444. return ((splay_tree_node) node);
  445. }
  446. static void m_splay_tree_free_key(splay_tree_key key)
  447. {
  448. if (key) {
  449. free((void *)key);
  450. }
  451. return;
  452. }
  453. /* Splay-tree comparison function, treating the keys as pointers.
  454. Note this is possibly not portable on all systems according to standards
  455. and may have undefined results. there seems no good solution for this.
  456. (a char datatype does not have to be a single byte in c for example)
  457. */
  458. static int m_splay_tree_compare_pointers(splay_tree_key k1, splay_tree_key k2)
  459. {
  460. /* 0==0 */
  461. if ((k1 == (splay_tree_key) 0) && (k2 == (splay_tree_key) 0)) {
  462. return (0);
  463. }
  464. /* possible undefined results at this, says the c standard. has to be understood as (signed char *) */
  465. if ((char *)k1 < (char *)k2) {
  466. return ((int)-1);
  467. } else if ((char *)k1 > (char *)k2) {
  468. return (1);
  469. } else {
  470. return (0);
  471. }
  472. }
  473. /* */
  474. static struct splay_tree_node_n *m_splay(splay_tree sp, splay_tree_key key)
  475. {
  476. struct splay_tree_node_n *t = (struct splay_tree_node_n *)0;
  477. struct splay_tree_node_n *l = (struct splay_tree_node_n *)0;
  478. struct splay_tree_node_n *r = (struct splay_tree_node_n *)0;
  479. struct splay_tree_node_n *y = (struct splay_tree_node_n *)0;
  480. int comparevalue = 0;
  481. int comparevalue2 = 0;
  482. struct splay_tree_node_n tmp = {
  483. /* The key. */
  484. (splay_tree_key) 0,
  485. /* The value. */
  486. (splay_tree_value) 0,
  487. /* The left and right children, respectively. */
  488. (struct splay_tree_node_n *)0, /* left */
  489. (struct splay_tree_node_n *)0 /* right */
  490. };
  491. /* no tree */
  492. if (sp == (splay_tree) 0) {
  493. return ((struct splay_tree_node_n *)0);
  494. }
  495. /* no data in root. return 0 */
  496. if (sp->root == (struct splay_tree_node_n *)0) {
  497. return ((struct splay_tree_node_n *)0);
  498. }
  499. /* current root */
  500. t = sp->root;
  501. tmp.left = (struct splay_tree_node_n *)0;
  502. tmp.right = (struct splay_tree_node_n *)0;
  503. l = &tmp;
  504. r = &tmp;
  505. labelstart:
  506. /* */
  507. comparevalue = (*sp->comp) (key, t->key);
  508. if (comparevalue < 0) {
  509. if (t->left == (struct splay_tree_node_n *)0) {
  510. goto labelend;
  511. }
  512. /* */
  513. comparevalue2 = (*sp->comp) (key, t->left->key);
  514. if (comparevalue2 < 0) {
  515. y = t->left;
  516. t->left = y->right;
  517. y->right = t;
  518. t = y;
  519. if (t->left == (struct splay_tree_node_n *)0) {
  520. goto labelend;
  521. }
  522. }
  523. /* */
  524. r->left = t;
  525. r = t;
  526. t = t->left;
  527. } else if (comparevalue > 0) {
  528. if (t->right == (struct splay_tree_node_n *)0) {
  529. goto labelend;
  530. }
  531. /* */
  532. comparevalue2 = (*sp->comp) (key, t->right->key);
  533. if (comparevalue2 > 0) {
  534. /* */
  535. y = t->right;
  536. t->right = y->left;
  537. y->left = t;
  538. t = y;
  539. if (t->right == (struct splay_tree_node_n *)0) {
  540. goto labelend;
  541. }
  542. }
  543. /* */
  544. l->right = t;
  545. l = t;
  546. t = t->right;
  547. } else {
  548. /* here if (comparevalue == 0) */
  549. goto labelend;
  550. }
  551. goto labelstart;
  552. labelend:
  553. l->right = t->left;
  554. r->left = t->right;
  555. t->left = tmp.right;
  556. t->right = tmp.left;
  557. sp->root = t;
  558. return ((struct splay_tree_node_n *)t);
  559. }
  560. /* end */
  561. static void memcheck_free(void *ptr)
  562. {
  563. splay_tree_node spn = NULL;
  564. char *p = NULL;
  565. if (memdata == NULL) {
  566. /* shouldnothappen */
  567. memdata = m_splay_tree_new(m_splay_tree_compare_pointers, m_splay_tree_free_key, NULL /* delete_value_fn */ );
  568. }
  569. if (ptr) {
  570. spn = m_splay_tree_lookup(memdata, (splay_tree_key) ptr);
  571. if (spn) {
  572. m_splay_tree_remove(memdata, (splay_tree_key) spn->key);
  573. } else {
  574. printf("%s(): %p not found\n", __func__, (void *)ptr);
  575. if (0) {
  576. *p = 10;
  577. }
  578. }
  579. }
  580. return;
  581. }
  582. static void *memcheck_calloc(size_t nmemb, size_t size)
  583. {
  584. void *ret = NULL;
  585. size_t total = 0;
  586. if (memdata == NULL) {
  587. memdata = m_splay_tree_new(m_splay_tree_compare_pointers, m_splay_tree_free_key, NULL /* delete_value_fn */ );
  588. }
  589. total = (nmemb * size);
  590. ret = calloc(1, total);
  591. m_splay_tree_insert(memdata, (splay_tree_key) ret, (splay_tree_value) total);
  592. return (ret);
  593. }
  594. static void *memcheck_realloc(void *ptr, size_t size)
  595. {
  596. void *ret = NULL;
  597. size_t oldsize = 0;
  598. splay_tree_node spn = NULL;
  599. if (ptr == NULL) {
  600. return (memcheck_calloc(1, size));
  601. }
  602. if (size == 0) {
  603. memcheck_free(ptr);
  604. return (0);
  605. }
  606. /* find the old size of the pointed to memory block */
  607. spn = m_splay_tree_lookup(memdata, (splay_tree_key) ptr);
  608. if (spn) {
  609. oldsize = (size_t)spn->value;
  610. /* new memory block */
  611. ret = memcheck_calloc(1, size);
  612. if (size > oldsize) {
  613. memmove(ret, ptr, oldsize);
  614. } else {
  615. /* if new size is smaller, copy part of old data */
  616. memmove(ret, ptr, size);
  617. }
  618. /* free old block */
  619. memcheck_free(ptr);
  620. }
  621. return (ret);
  622. }
  623. void dp_memreport(void)
  624. {
  625. splay_tree_node spn = NULL;
  626. size_t total = 0;
  627. int i = 0;
  628. if (memdata == NULL) {
  629. return;
  630. }
  631. if (m_splay_tree_has_data(memdata)) {
  632. spn = m_splay_tree_min(memdata);
  633. i = 1;
  634. while (spn) {
  635. printf("%s(): pointer[%d] %p with %d bytes not free'ed\n", __func__, i, (void *)spn->key, (int)spn->value);
  636. total += (size_t)spn->value;
  637. i++;
  638. spn = m_splay_tree_successor(memdata, spn->key);
  639. }
  640. }
  641. if (total) {
  642. printf("%s(): total %d bytes memory leak at exit\n", __func__, (int)total);
  643. } else {
  644. printf("%s(): no memory leak at exit\n", __func__);
  645. }
  646. memdata = m_splay_tree_delete(memdata);
  647. return;
  648. }
  649. void dp_meminit(void)
  650. {
  651. if (memdata == NULL) {
  652. memdata = m_splay_tree_new(m_splay_tree_compare_pointers, m_splay_tree_free_key, NULL /* delete_value_fn */ );
  653. }
  654. return;
  655. }
  656. #else
  657. /* no memory checking */
  658. /* */
  659. void dp_memreport(void)
  660. {
  661. if (memdata) {
  662. }
  663. memdata = NULL;
  664. return;
  665. }
  666. static void memcheck_free(void *ptr)
  667. {
  668. if (ptr) {
  669. #ifdef CLIB
  670. free(ptr);
  671. #else
  672. g_free(ptr);
  673. #endif
  674. }
  675. return;
  676. }
  677. static void *memcheck_calloc(size_t nmemb, size_t size)
  678. {
  679. #ifdef CLIB
  680. return (calloc(1, (nmemb * size)));
  681. #else
  682. return (g_malloc0((nmemb * size)));
  683. #endif
  684. }
  685. static void *memcheck_realloc(void *ptr, size_t size)
  686. {
  687. #ifdef CLIB
  688. return (realloc(ptr, size));
  689. #else
  690. return (g_realloc(ptr, size));
  691. #endif
  692. }
  693. void dp_meminit(void)
  694. {
  695. return;
  696. }
  697. #endif
  698. /* end */