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