1 #undef _MEMORY_DEBUG_
2 #include "psqlodbc.h"
3
4 #ifdef WIN32
5 #ifdef _DEBUG
6 /* #include <stdlib.h> */
7 #define _CRTDBG_MAP_ALLOC
8 #include <crtdbg.h>
9 #else
10 #include <malloc.h>
11 #endif /* _DEBUG */
12 #endif /* WIN32 */
13 #include <string.h>
14
15 #include "misc.h"
16 typedef struct {
17 size_t len;
18 void *aladr;
19 } ALADR;
20
21 static int alsize = 0;
22 static int tbsize = 0;
23 static ALADR *altbl = NULL;
24
25 CSTR ALCERR = "alcerr";
pgdebug_alloc(size_t size)26 void * pgdebug_alloc(size_t size)
27 {
28 void * alloced;
29 alloced = malloc(size);
30 MYLOG(2, " alloced=%p(" FORMAT_SIZE_T ")\n", alloced, size);
31 if (alloced)
32 {
33 if (!alsize)
34 {
35 alsize = 100;
36 altbl = (ALADR *) malloc(alsize * sizeof(ALADR));
37 }
38 else if (tbsize >= alsize)
39 {
40 ALADR *al;
41 alsize *= 2;
42 if (al = (ALADR *) realloc(altbl, alsize * sizeof(ALADR)), NULL == al)
43 return alloced;
44 altbl = al;
45 }
46 altbl[tbsize].aladr = alloced;
47 altbl[tbsize].len = size;
48 tbsize++;
49 }
50 else
51 MYLOG(0, "%s:alloc " FORMAT_SIZE_T "byte\n", ALCERR, size);
52 return alloced;
53 }
pgdebug_calloc(size_t n,size_t size)54 void * pgdebug_calloc(size_t n, size_t size)
55 {
56 void * alloced = calloc(n, size);
57
58 if (alloced)
59 {
60 if (!alsize)
61 {
62 alsize = 100;
63 altbl = (ALADR *) malloc(alsize * sizeof(ALADR));
64 }
65 else if (tbsize >= alsize)
66 {
67 ALADR *al;
68 alsize *= 2;
69 if (al = (ALADR *) realloc(altbl, alsize * sizeof(ALADR)), NULL == al)
70 return alloced;
71 altbl = al;
72 }
73 altbl[tbsize].aladr = alloced;
74 altbl[tbsize].len = n * size;
75 tbsize++;
76 }
77 else
78 MYLOG(0, "%s:calloc " FORMAT_SIZE_T "byte\n", ALCERR, size);
79 MYLOG(2, "calloced = %p\n", alloced);
80 return alloced;
81 }
pgdebug_realloc(void * ptr,size_t size)82 void * pgdebug_realloc(void * ptr, size_t size)
83 {
84 void * alloced;
85
86 if (!ptr)
87 return pgdebug_alloc(size);
88 alloced = realloc(ptr, size);
89 if (!alloced)
90 {
91 MYLOG(0, "%s %p error\n", ALCERR, ptr);
92 }
93 else /* if (alloced != ptr) */
94 {
95 int i;
96 for (i = 0; i < tbsize; i++)
97 {
98 if (altbl[i].aladr == ptr)
99 {
100 altbl[i].aladr = alloced;
101 altbl[i].len = size;
102 break;
103 }
104 }
105 }
106
107 MYLOG(2, "%p->%p\n", ptr, alloced);
108 return alloced;
109 }
pgdebug_strdup(const char * ptr)110 char * pgdebug_strdup(const char * ptr)
111 {
112 char * alloced = strdup(ptr);
113 if (!alloced)
114 {
115 MYLOG(0, "%s %p error\n", ALCERR, ptr);
116 }
117 else
118 {
119 if (!alsize)
120 {
121 alsize = 100;
122 altbl = (ALADR *) malloc(alsize * sizeof(ALADR));
123 }
124 else if (tbsize >= alsize)
125 {
126 ALADR *al;
127 alsize *= 2;
128 if (al = (ALADR *) realloc(altbl, alsize * sizeof(ALADR)), NULL == al)
129 return alloced;
130 altbl = al;
131 }
132 altbl[tbsize].aladr = alloced;
133 altbl[tbsize].len = strlen(ptr) + 1;
134 tbsize++;
135 }
136 MYLOG(2, "%p->%p(%s)\n", ptr, alloced, alloced);
137 return alloced;
138 }
139
pgdebug_free(void * ptr)140 void pgdebug_free(void * ptr)
141 {
142 int i, j;
143 int freed = 0;
144
145 if (!ptr)
146 {
147 MYLOG(0, "%s null ptr\n", ALCERR);
148 return;
149 }
150 for (i = 0; i < tbsize; i++)
151 {
152 if (altbl[i].aladr == ptr)
153 {
154 for (j = i; j < tbsize - 1; j++)
155 {
156 altbl[j].aladr = altbl[j + 1].aladr;
157 altbl[j].len = altbl[j + 1].len;
158 }
159 tbsize--;
160 freed = 1;
161 break;
162 }
163 }
164 if (! freed)
165 {
166 MYLOG(0, "%s not found ptr %p\n", ALCERR, ptr);
167 return;
168 }
169 else
170 MYLOG(2, "ptr=%p\n", ptr);
171 free(ptr);
172 }
173
out_check(void * out,size_t len,const char * name)174 static BOOL out_check(void *out, size_t len, const char *name)
175 {
176 BOOL ret = TRUE;
177 int i;
178
179 for (i = 0; i < tbsize; i++)
180 {
181 if ((ULONG_PTR)out < (ULONG_PTR)(altbl[i].aladr))
182 continue;
183 if ((ULONG_PTR)out < (ULONG_PTR)(altbl[i].aladr) + altbl[i].len)
184 {
185 if ((ULONG_PTR)out + len > (ULONG_PTR)(altbl[i].aladr) + altbl[i].len)
186 {
187 ret = FALSE;
188 MYLOG(0, "%s:%s:out_check found memory buffer overrun %p(" FORMAT_SIZE_T ")>=%p(" FORMAT_SIZE_T ")\n", ALCERR, name, out, len, altbl[i].aladr, altbl[i].len);
189 }
190 break;
191 }
192 }
193 return ret;
194 }
pgdebug_strcpy(char * out,const char * in)195 char *pgdebug_strcpy(char *out, const char *in)
196 {
197 if (!out || !in)
198 {
199 MYLOG(0, "%s null pointer out=%p,in=%p\n", ALCERR, out, in);
200 return NULL;
201 }
202 out_check(out, strlen(in) + 1, __FUNCTION__);
203 return strcpy(out, in);
204 }
pgdebug_strncpy(char * out,const char * in,size_t len)205 char *pgdebug_strncpy(char *out, const char *in, size_t len)
206 {
207 if (!out || !in)
208 {
209 MYLOG(0, "%s null pointer out=%p,in=%p\n", ALCERR, out, in);
210 return NULL;
211 }
212 out_check(out, len, __FUNCTION__);
213 return strncpy(out, in, len);
214 }
pgdebug_strncpy_null(char * out,const char * in,size_t len)215 char *pgdebug_strncpy_null(char *out, const char *in, size_t len)
216 {
217 if (!out || !in)
218 {
219 MYLOG(0, "%s null pointer out=%p,in=%p\n", ALCERR, out, in);
220 return NULL;
221 }
222 out_check(out, len, __FUNCTION__);
223 strncpy_null(out, in, len);
224 return out;
225 }
226
pgdebug_memcpy(void * out,const void * in,size_t len)227 void *pgdebug_memcpy(void *out, const void *in, size_t len)
228 {
229 if (!out || !in)
230 {
231 MYLOG(0, "%s null pointer out=%p,in=%p\n", ALCERR, out, in);
232 return NULL;
233 }
234 out_check(out, len, __FUNCTION__);
235 return memcpy(out, in, len);
236 }
237
pgdebug_memset(void * out,int c,size_t len)238 void *pgdebug_memset(void *out, int c, size_t len)
239 {
240 if (!out)
241 {
242 MYLOG(0, "%s null pointer out=%p\n", ALCERR, out);
243 return NULL;
244 }
245 out_check(out, len, __FUNCTION__);
246 return memset(out, c, len);
247 }
248
debug_memory_check(void)249 void debug_memory_check(void)
250 {
251 int i;
252
253 if (0 == tbsize)
254 {
255 MYLOG(0, "no memry leak found and max count allocated so far is %d\n", alsize);
256 free(altbl);
257 alsize = 0;
258 }
259 else
260 {
261 MYLOG(0, "%s:memory leak found check count=%d alloc=%d\n", ALCERR, tbsize, alsize);
262 for (i = 0; i < tbsize; i++)
263 {
264 MYLOG(0, "%s:leak = %p(" FORMAT_SIZE_T ")\n", ALCERR, altbl[i].aladr, altbl[i].len);
265 }
266 }
267 }
268