2 Copyright (C) Andrew Tridgell 2002
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 a malloc wrapper library for the dynamically loaded part of
21 chessd. This is used both as a malloc checker library and to prevent
22 some bad interactions between the dl library and malloc
30 #define MAGIC1 0x28021967
31 #define MAGIC2 0x26011966
35 struct malloc_list *next;
36 struct malloc_list *prev;
39 static struct malloc_list *mlist;
42 struct malloc_header {
43 struct malloc_list *m;
49 a magic-value protected malloc wrapper,
50 which can be globally freed using a single call
52 void *m_malloc(size_t size)
55 struct malloc_list *m;
56 struct malloc_header *h;
58 if (size == 0) return NULL;
60 ptr = malloc(size+sizeof(struct malloc_header));
62 if (!ptr) return NULL;
64 m = malloc(sizeof(*m));
67 fprintf(stderr,"malloc %p %u\n", ptr, size);
68 fprintf(stderr,"malloc %p\n", m);
86 memset(ptr, 0, size+sizeof(struct malloc_header));
97 determine the size of a malloced region
99 static size_t m_malloc_size(void *ptr)
101 struct malloc_header *h;
104 h = (struct malloc_header *)ptr;
111 check that a pointer is OK
113 void m_malloc_check(void *ptr)
115 struct malloc_header *h;
119 h = (struct malloc_header *)ptr;
122 if (h->magic != MAGIC1) {
123 d_printf("malloc corruption ptr=%p v1=%x size=%d\n",
124 ptr, h->magic, h->size);
129 a paranoid free() function that checks for simple corruption
131 int m_free(void *ptr)
133 struct malloc_header *h;
134 struct malloc_list *m;
138 h = (struct malloc_header *)ptr;
141 if (h->magic != MAGIC1) {
142 d_printf("malloc corruption ptr=%p v1=%x size=%d\n",
143 ptr, h->magic, h->size);
148 if (!m || m->ptr != h) {
149 d_printf("malloc list corruption!\n");
152 m->next->prev = m->prev;
155 m->prev->next = m->next;
164 fprintf(stderr,"free %p %u\n", h, h->size);
165 fprintf(stderr,"free %p\n", m);
168 memset(ptr, 'Z', h->size); /* paranoia */
169 memset(m, 0, sizeof(*m));
171 memset(h, 0, sizeof(*h));
177 check all allocated memory
179 void m_check_all(void)
181 struct malloc_list *m;
182 for (m=mlist; m; m=m->next) {
183 m_malloc_check(m->ptr + sizeof(struct malloc_header));
189 free all allocated memory
191 void m_free_all(void)
193 struct malloc_list *m, *next;
194 d_printf("Freeing %d chunks\n", m_total);
195 for (m=mlist; m; m=next) {
200 fprintf(stderr,"free %p\n", m->ptr);
201 fprintf(stderr,"free %p\n", m);
209 /* a calloc wrapper */
210 void *m_calloc(size_t n, size_t size)
213 ptr = m_malloc(n*size);
214 if (ptr) memset(ptr, 0, n*size);
219 char *m_strdup(const char *s)
223 ret = m_malloc(len+1);
224 memcpy(ret, s, len+1);
228 /* strndup wrapper */
229 char *m_strndup(const char *s, size_t n)
231 int len = strnlen(s, n);
233 ret = m_malloc(len+1);
239 /* a free() call that zeros the pointer to prevent re-use */
240 void m_safe_free(void **ptr, const char *file, unsigned line)
243 d_printf("NULL free at %s(%u)!\n", file, line);
246 if (m_free(*ptr) != 0) {
247 d_printf("bad free at %s(%u)!\n", file, line);
253 /* a vasprintf wrapper */
254 int m_vasprintf(char **strp, const char *fmt, va_list ap)
260 n = vsnprintf(NULL, 0, fmt, ap);
261 if (n == 0) return 0;
263 (*strp) = m_malloc(n+1);
264 n = vsnprintf(*strp, n+1, fmt, ap);
269 /* a asprintf wrapper */
270 int m_asprintf(char **strp, const char *fmt, ...)
276 n = m_vasprintf(strp, fmt, ap);
282 /* a realloc wrapper */
283 void *m_realloc(void *ptr, size_t size)
289 return m_malloc(size);
293 m_safe_free(&ptr, __FILE__, __LINE__);
297 ret = m_malloc(size);
299 msize = m_malloc_size(ptr);
300 memcpy(ret, ptr, size<msize?size:msize);
301 m_safe_free(&ptr, __FILE__, __LINE__);