memdebug.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /* Implementation of memdebug.h */
  2. #include "conf.h"
  3. #ifdef MEMLEAK_DEBUG
  4. #include "memdebug.h"
  5. #include <assert.h>
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <stdarg.h>
  9. /* ----------------- configuration ----------------- */
  10. #define NCHUNKS 8092
  11. /* --------------- type definitions -------------- */
  12. typedef struct {
  13. void* ptr;
  14. size_t size;
  15. } MemChunk;
  16. /* ----------------- local function declarations ----------------- */
  17. static void logmsg(const char *msg, ...);
  18. /* ----------------- local variables ----------------- */
  19. static MemChunk mem_chunks[NCHUNKS];
  20. static size_t mem_tot;
  21. static size_t n_allocs;
  22. static size_t n_frees;
  23. /* --------------------------------------- */
  24. void memdebug_setup()
  25. {
  26. /* handle multiple calls */
  27. static int setup_done = 0;
  28. int i;
  29. if (setup_done) {
  30. return;
  31. }
  32. for (i = 0; i < NCHUNKS; i++) {
  33. mem_chunks[i].ptr = NULL;
  34. mem_chunks[i].size = 0;
  35. }
  36. mem_tot = 0;
  37. n_allocs = 0;
  38. n_frees = 0;
  39. setup_done = 1;
  40. }
  41. /* --------------------------------------- */
  42. void* memdebug_calloc(size_t nobj, size_t size)
  43. {
  44. void *obj = calloc(nobj, size);
  45. ++n_allocs;
  46. if (obj != NULL) {
  47. size_t tot_size = nobj * size;
  48. int i = 0;
  49. while (i < NCHUNKS && mem_chunks[i].ptr != NULL) {
  50. ++i;
  51. }
  52. assert(i < NCHUNKS);
  53. mem_chunks[i].ptr = obj;
  54. mem_chunks[i].size = tot_size;
  55. mem_tot += tot_size;
  56. } else {
  57. logmsg("calloc failed!");
  58. assert(0);
  59. }
  60. return obj;
  61. }
  62. /* --------------------------------------- */
  63. void memdebug_free(void* obj)
  64. {
  65. int i = 0;
  66. if (obj == NULL) {
  67. return;
  68. }
  69. while (i < NCHUNKS && mem_chunks[i].ptr != obj) {
  70. ++i;
  71. }
  72. if (i == NCHUNKS) {
  73. logmsg("free attempted on un-allocated pointer: %p!", obj);
  74. assert(0);
  75. return;
  76. }
  77. assert(i < NCHUNKS);
  78. free(obj);
  79. ++n_frees;
  80. mem_chunks[i].ptr = NULL;
  81. mem_tot -= mem_chunks[i].size;
  82. }
  83. /* --------------------------------------- */
  84. void memdebug_check()
  85. {
  86. int i;
  87. for (i = 0; i < NCHUNKS; i++) {
  88. if (mem_chunks[i].ptr != NULL) {
  89. logmsg("memory on index %d: %p not freed: %d bytes", i, mem_chunks[i].ptr, mem_chunks[i].size);
  90. }
  91. }
  92. if (mem_tot > 0) {
  93. logmsg("memory leak: %u bytes", mem_tot);
  94. } else {
  95. logmsg("no memory leaks");
  96. }
  97. }
  98. /* ----------------- local function definitions ----------------- */
  99. static void logmsg(const char *msg, ...)
  100. {
  101. char buf[256];
  102. va_list ap;
  103. va_start(ap, msg);
  104. vsnprintf(buf, sizeof(buf) - 1, msg, ap);
  105. va_end(ap);
  106. printf("MEMORY DEBUG: %s\n", buf);
  107. }
  108. #endif