1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdarg.h>
5
6 #include <glib.h>
7
8 #include "mem.h"
9
10 #ifdef MEM_TEST
11
12 #define MEM_DONT_FREE
13
14 #define MAGIC_PRE_HASH 0xdeadbeef
15 #define MAGIC_POST_HASH 0xabcdef12
16
17 #define memsql_error(fmt,args...) fprintf (stderr, "MEM: " fmt "\n" , ##args)
18 #define min(a,b) (((a) > (b)) ? (b) : (a))
19
20 typedef struct
21 {
22 int pre_id;
23 char name[64];
24 int size;
25 int line;
26 char file[32];
27 #ifdef MEM_DONT_FREE
28
29 int freed;
30 #endif
31 }
32 memsql_pre_info;
33
34 typedef struct
35 {
36 int post_id;
37 }
38 memsql_post_info;
39
40 static GList *memsql_list = NULL;
41
42 static void *
memsql_get_post(memsql_pre_info * pre)43 memsql_get_post (memsql_pre_info * pre)
44 {
45 return ((char *) pre) + sizeof (memsql_pre_info) + pre->size;
46 }
47
48 static void *
memsql_get_data(memsql_pre_info * pre)49 memsql_get_data (memsql_pre_info * pre)
50 {
51 return ((char *) pre) + sizeof (memsql_pre_info);
52 }
53
54 static memsql_pre_info *
memsql_get_pre(void * data)55 memsql_get_pre (void *data)
56 {
57 return (void *) (((char *) data) - sizeof (memsql_pre_info));
58 }
59
60 char *
memsql_strdup_raw(char * funcname,int linenum,char * file,char * string)61 memsql_strdup_raw (char *funcname, int linenum, char *file, char *string)
62 {
63 char *data;
64
65 if (!string)
66 return NULL;
67
68 data = memsql_alloc_raw (funcname, linenum, file, strlen (string) + 1);
69 if (data)
70 strcpy (data, string);
71
72 return data;
73 }
74
75 void *
memsql_strdup_printf_raw(char * funcname,int linenum,char * file,const char * fmt,...)76 memsql_strdup_printf_raw (char *funcname, int linenum, char *file,
77 const char *fmt, ...)
78 {
79 void *retptr;
80 gchar *tmpstr;
81 va_list args;
82 va_start (args, fmt);
83 tmpstr = g_strdup_vprintf (fmt, args);
84 retptr = memsql_strdup_raw (funcname, linenum, file, tmpstr);
85 g_free (tmpstr);
86 return retptr;
87 }
88
89 void *
memsql_alloc_raw(char * funcname,int linenum,char * file,int count)90 memsql_alloc_raw (char *funcname, int linenum, char *file, int count)
91 {
92 int real_size;
93 memsql_pre_info *pre;
94 memsql_post_info *post;
95
96 real_size = count + sizeof (memsql_pre_info) + sizeof (memsql_post_info);
97
98 pre = malloc (real_size);
99
100 if (!pre) {
101 memsql_error ("Memory full");
102 return NULL;
103 }
104
105 strncpy (pre->name, funcname, 63);
106 pre->name[63] = '\0';
107 strncpy (pre->file, file, 31);
108 pre->file[31] = '\0';
109 pre->line = linenum;
110 pre->size = count;
111 #ifdef MEM_DONT_FREE
112
113 pre->freed = 0;
114 #endif
115
116 post = memsql_get_post (pre);
117
118 pre->pre_id = MAGIC_PRE_HASH;
119 post->post_id = MAGIC_POST_HASH;
120
121 memsql_list = g_list_append (memsql_list, pre);
122
123 return memsql_get_data (pre);
124 }
125
126 void *
memsql_calloc_raw(char * funcname,int linenum,char * file,int count)127 memsql_calloc_raw (char *funcname, int linenum, char *file, int count)
128 {
129 void *ptr;
130
131 ptr = memsql_alloc_raw (funcname, linenum, file, count);
132 if (ptr)
133 memset (ptr, 0, count);
134
135 return ptr;
136 }
137
138 void *
memsql_realloc_raw(char * funcname,int linenum,char * file,void * mem,int count)139 memsql_realloc_raw (char *funcname, int linenum, char *file, void *mem,
140 int count)
141 {
142 void *new_mem;
143 memsql_pre_info *pre;
144
145 new_mem = memsql_alloc_raw (funcname, linenum, file, count);
146 pre = memsql_get_pre (new_mem);
147 if (mem != NULL)
148 memcpy (new_mem, mem, min (count, pre->size));
149
150 memsql_free (mem);
151
152 return new_mem;
153 }
154
155 int
memsql_free(void * mem)156 memsql_free (void *mem)
157 {
158 memsql_pre_info *pre;
159 memsql_post_info *post;
160
161 if (!mem)
162 return 0;
163
164 pre = memsql_get_pre (mem);
165
166 if (pre->pre_id != MAGIC_PRE_HASH) {
167 memsql_error ("pre hash doesn't match on: %s", pre->name);
168 g_assert (NULL);
169 }
170 post = memsql_get_post (pre);
171 if (post->post_id != MAGIC_POST_HASH) {
172 memsql_error ("post hash doesn't match on: %s", pre->name);
173 g_assert (NULL);
174 }
175
176 /* memsql_error ("mem list length: %d", g_list_length (memsql_list)); */
177
178 #ifdef MEM_DONT_FREE
179 if (pre->freed)
180 memsql_error ("freeing memory block `%s' for a second time", pre->name);
181
182 pre->freed = 1;
183 #else
184
185 memsql_list = g_list_remove (memsql_list, pre);
186 free (pre);
187 #endif
188
189 return 0;
190 }
191
192 int
memsql_display(void)193 memsql_display (void)
194 {
195 void *buf;
196 GList *cur;
197 memsql_pre_info *pre;
198 int count = 0;
199 int bytes = 0, i;
200
201 for (cur = memsql_list; cur != NULL; cur = cur->next) {
202 pre = cur->data;
203 #ifdef MEM_DONT_FREE
204
205 if (!pre->freed) {
206 #endif
207 memsql_error ("%s: %d: %s() %dbytes still alloced", pre->file,
208 pre->line, pre->name, pre->size);
209 /* Uncomment this if you want to display the memory buffer */
210 buf = memsql_get_data (pre);
211 if (pre->size > 256);
212 else {
213 for (i = 0; i < pre->size; i++) {
214 if (*((char *) buf) >= ' ' && *((char *) buf) <= 'z')
215 fprintf (stderr, "%c", *((char *) buf));
216 ((char *) buf)++;
217 }
218 fprintf (stderr, "\n");
219 }
220 count++;
221 bytes += pre->size;
222 #ifdef MEM_DONT_FREE
223
224 }
225 #endif
226
227 }
228
229 /*if (count) */
230 memsql_error ("%d memory leaks, totaling %d bytes", count, bytes);
231
232 return 0;
233 }
234 #endif
235
236 char *
memsql_strappend_raw(const char * funcname,int linenum,char * file,char * string1,char * string2)237 memsql_strappend_raw (const char *funcname, int linenum, char *file, char *string1,
238 char *string2)
239 {
240 int len = 0;
241 char *retval;
242
243 /* memsql_error ("appending: %s, %s", string1, string2); */
244
245 if (!string1 && !string2)
246 return NULL;
247
248 if (string1)
249 len += strlen (string1);
250 if (string2)
251 len += strlen (string2);
252 retval = g_malloc (len + 1);
253 retval[0] = '\0';
254
255 if (string1)
256 strcpy (retval, string1);
257 if (string2)
258 strcat (retval, string2);
259
260 retval[len] = '\0';
261
262 return retval;
263 }
264
265 char *
memsql_strappend_free_raw(const char * funcname,int linenum,char * file,char * str1,char * str2)266 memsql_strappend_free_raw (const char *funcname, int linenum, char *file,
267 char *str1, char *str2)
268 {
269 char *retval;
270
271 retval = memsql_strappend_raw (funcname, linenum, file, str1, str2);
272
273 if (str1)
274 memsql_free (str1);
275 if (str2)
276 memsql_free (str2);
277
278 return retval;
279 }
280