2 #include "codemuxlib.h"
6 #ifdef DEBUG_MEMORY_LEAK
8 /* Maximum length of the location string containing function, file and
9 the line number of the memory allocation part in the original
10 source code. The location info is added in front of the pointer
11 when allocating memory and return p + MAX_LOCATION_STRLEN to the
13 #define MAX_LOCATION_STRLEN 512
15 typedef struct MemoryAllocInfo {
16 char *mi_locstr; /* location string "__FUNCTION__:__LINE__" */
17 int mi_count; /* allocated memory counts */
18 LIST_ENTRY(MemoryAllocInfo) mi_hash;
19 LIST_ENTRY(MemoryAllocInfo) mi_all;
22 #define MAX_BINS 257 /* a prime number near 256 */
23 static LIST_HEAD(, MemoryAllocInfo) miBins[MAX_BINS];
24 static LIST_HEAD(, MemoryAllocInfo) miHead = LIST_HEAD_INITIALIZER(miHead);
26 /*-------------------------------------------------------------------------*/
28 dbg_print_memtrace(void)
30 MemoryAllocInfo *walk;
32 TRACE("memory alloc counts dump begins\n");
33 LIST_FOREACH(walk, &miHead, mi_all) {
34 TRACE("%-50s: %d\n", walk->mi_locstr, walk->mi_count);
36 TRACE("memory alloc counts dump ends\n");
38 /*-------------------------------------------------------------------------*/
40 increase_alloc_count(char* p, const char* func,
41 const char* file, const int line)
44 MemoryAllocInfo* walk;
46 #define MAX_LINE_DIGIT 7 /* million lines of code per file is way too much */
47 #define LOCSTR_LENGH (strlen(func) + strlen(file) + MAX_LINE_DIGIT + 3)
49 if (LOCSTR_LENGH >= MAX_LOCATION_STRLEN) {
50 TRACE("over the length limit %s:%d\n", func, line);
54 snprintf(p, MAX_LOCATION_STRLEN, "%s:%s:%d", func, file, line);
56 bin = (int)(HashString(p, 0, FALSE, FALSE) % MAX_BINS);
57 LIST_FOREACH(walk, &miBins[bin], mi_hash) {
58 if (strcmp(walk->mi_locstr, p) == 0) { /* match */
64 /* allocate it if not found */
65 if ((walk = (MemoryAllocInfo *)calloc(1, sizeof(MemoryAllocInfo))) == NULL) {
66 TRACE("calloc failed\n");
70 if ((walk->mi_locstr = strdup(p)) == NULL) {
71 TRACE("calloc failed\n");
76 LIST_INSERT_HEAD(&miBins[bin], walk, mi_hash);
77 LIST_INSERT_HEAD(&miHead, walk, mi_all);
79 /*-------------------------------------------------------------------------*/
81 decrease_alloc_count(char *p, const char* func,
82 const char* file, const int line)
84 int bin = (int)(HashString(p, 0, FALSE, FALSE) % MAX_BINS);
85 MemoryAllocInfo* walk;
87 LIST_FOREACH(walk, &miBins[bin], mi_hash) {
88 if (strcmp(walk->mi_locstr, p) == 0) { /* match */
90 if (walk->mi_count == 0) {
91 LIST_REMOVE(walk, mi_hash);
92 LIST_REMOVE(walk, mi_all);
93 free(walk->mi_locstr);
100 TRACE("decrease failed %s:%s:%d\n", func, file, line);
101 FlushLogF(hdebugLog);
104 /*-------------------------------------------------------------------------*/
106 dbgcalloc(size_t nmemb, size_t size,
107 const char* func, const char* file, const int line)
109 int msize = nmemb * size + MAX_LOCATION_STRLEN;
112 if ((p = (char *)calloc(1, msize)) != NULL) {
113 increase_alloc_count(p, func, file, line);
114 return (void *)(p + MAX_LOCATION_STRLEN);
118 /*-------------------------------------------------------------------------*/
120 dbgmalloc(size_t size, const char* func, const char* file, const int line)
122 int msize = size + MAX_LOCATION_STRLEN;
125 if ((p = (char *)malloc(msize)) != NULL) {
126 increase_alloc_count(p, func, file, line);
127 return (void *)(p + MAX_LOCATION_STRLEN);
131 /*-------------------------------------------------------------------------*/
133 dbgrealloc(void *ptr, size_t size,
134 const char* func, const char* file, const int line)
136 int msize = size + MAX_LOCATION_STRLEN;
140 ptr -= MAX_LOCATION_STRLEN;
141 decrease_alloc_count(ptr, func, file, line);
144 if ((p = (char *)realloc(ptr, msize)) != NULL) {
145 increase_alloc_count(p, func, file, line);
146 return (void *)(p + MAX_LOCATION_STRLEN);
150 /*-------------------------------------------------------------------------*/
152 dbgstrdup(const char *s, const char* func, const char* file, const int line)
154 int msize = strlen(s) + 1 + MAX_LOCATION_STRLEN;
157 if ((p = (char *)malloc(msize))) {
158 increase_alloc_count(p, func, file, line);
159 p += MAX_LOCATION_STRLEN;
165 /*-------------------------------------------------------------------------*/
167 dbgfree(void *ptr, const char* func, const char* file, const int line)
169 /* should free the original pointer */
170 char* chptr = (char *)ptr;
172 chptr -= MAX_LOCATION_STRLEN;
173 decrease_alloc_count(chptr, func, file, line);