1 /* this code is stolen from the links browser, it was written by Mikulas Patocka */
30 struct xlist_head
*next
;
31 struct xlist_head
*prev
;
37 #define del_from_list(x) {((struct list_head *)(x)->next)->prev=(x)->prev; ((struct list_head *)(x)->prev)->next=(x)->next;}
38 #define add_at_pos(p,x) do {(x)->next=(p)->next; (x)->prev=(p); (p)->next=(x); (x)->next->prev=(x);} while(0)
41 #define foreach(e,l) for ((e)=(l).next; (e)!=(typeof(e))&(l); (e)=(e)->next)
42 #define add_to_list(l,x) add_at_pos((typeof(x))&(l),(x))
44 #define foreach(e,l) for ((e)=(l).next; (e)!=(void *)&(l); (e)=(e)->next)
45 #define add_to_list(l,x) add_at_pos((struct xlist_head *)&(l),(struct xlist_head *)(x))
53 extern long mem_amount
;
54 extern long last_mem_amount
;
56 #define ALLOC_MAGIC 0xa110c
57 #define ALLOC_FREE_MAGIC 0xf4ee
58 #define ALLOC_REALLOC_MAGIC 0x4ea110c
60 #ifndef LEAK_DEBUG_LIST
67 struct alloc_header
*next
;
68 struct alloc_header
*prev
;
77 #define L_D_S ((sizeof(struct alloc_header) + 7) & ~7)
81 /*-----------------------------------------------------------------------------*/
83 void do_not_optimize_here(void *p
)
86 /* stop GCC optimization - avoid bugs in it */
91 long last_mem_amount
= -1;
92 #ifdef LEAK_DEBUG_LIST
93 struct list_head memory_list
= { &memory_list
, &memory_list
};
97 static inline void force_dump(void)
99 fprintf(stderr
, "\n\033[1m%s\033[0m\n", "Forcing core dump");
104 void check_memory_leaks(void)
108 fprintf(stderr
, "\n\033[1mMemory leak by %ld bytes\033[0m\n", mem_amount
);
109 #ifdef LEAK_DEBUG_LIST
110 fprintf(stderr
, "\nList of blocks: ");
113 struct alloc_header
*ah
;
114 foreach (ah
, memory_list
) {
115 fprintf(stderr
, "%s%p:%d @ %s:%d", r
? ", ": "", (char *)ah
+ L_D_S
, ah
->size
, ah
->file
, ah
->line
), r
= 1;
116 if (ah
->comment
) fprintf(stderr
, ":\"%s\"", ah
->comment
);
118 fprintf(stderr
, "\n");
126 void er(int b
, char *m
, va_list l
)
128 if (b
) fprintf(stderr
, "%c", (char)7);
129 vfprintf(stderr
, m
, l
);
130 fprintf(stderr
, "\n");
135 void error(char *m
, ...)
148 void int_error(char *m
, ...)
152 snprintf(errbuf
, sizeof(errbuf
), "\033[1mINTERNAL ERROR\033[0m at %s:%d: ", errfile
, errline
);
158 void debug_msg(char *m
, ...)
162 snprintf(errbuf
, sizeof(errbuf
), "DEBUG MESSAGE at %s:%d: ", errfile
, errline
);
169 void *debug_mem_alloc(char *file
, int line
, size_t size
)
173 struct alloc_header
*ah
;
175 if (!size
) return DUMMY
;
180 if (!(p
= malloc(size
))) {
181 error("ERROR: out of memory (malloc returned NULL)\n");
186 p
= (char *)p
+ L_D_S
;
187 ah
->size
= size
- L_D_S
;
188 ah
->magic
= ALLOC_MAGIC
;
189 #ifdef LEAK_DEBUG_LIST
193 add_to_list(memory_list
, ah
);
196 memset(p
, 'A', size
- L_D_S
);
200 void *debug_mem_calloc(char *file
, int line
, size_t size
)
204 struct alloc_header
*ah
;
206 if (!size
) return DUMMY
;
211 if (!(p
= x_calloc(size
))) {
212 error("ERROR: out of memory (calloc returned NULL)\n");
217 p
= (char *)p
+ L_D_S
;
218 ah
->size
= size
- L_D_S
;
219 ah
->magic
= ALLOC_MAGIC
;
220 #ifdef LEAK_DEBUG_LIST
224 add_to_list(memory_list
, ah
);
230 void debug_mem_free(char *file
, int line
, void *p
)
233 struct alloc_header
*ah
;
235 if (p
== DUMMY
) return;
237 errfile
= file
, errline
= line
, int_error("mem_free(NULL)");
241 p
= (char *)p
- L_D_S
;
243 if (ah
->magic
!= ALLOC_MAGIC
) {
244 errfile
= file
, errline
= line
, int_error("mem_free: magic doesn't match: %08x", ah
->magic
);
247 ah
->magic
= ALLOC_FREE_MAGIC
;
248 #ifdef LEAK_DEBUG_LIST
250 if (ah
->comment
) free(ah
->comment
);
252 mem_amount
-= ah
->size
;
257 void *debug_mem_realloc(char *file
, int line
, void *p
, size_t size
)
260 struct alloc_header
*ah
;
262 if (p
== DUMMY
) return debug_mem_alloc(file
, line
, size
);
264 errfile
= file
, errline
= line
, int_error("mem_realloc(NULL, %d)", size
);
268 debug_mem_free(file
, line
, p
);
272 p
= (char *)p
- L_D_S
;
274 if (ah
->magic
!= ALLOC_MAGIC
) {
275 errfile
= file
, errline
= line
, int_error("mem_realloc: magic doesn't match: %08x", ah
->magic
);
278 ah
->magic
= ALLOC_REALLOC_MAGIC
;
280 if (!(p
= realloc(p
, size
+ L_D_S
))) {
281 error("ERROR: out of memory (realloc returned NULL)\n");
286 mem_amount
+= size
- ah
->size
;
288 ah
->magic
= ALLOC_MAGIC
;
289 #ifdef LEAK_DEBUG_LIST
294 return (char *)p
+ L_D_S
;
297 void set_mem_comment(void *p
, char *c
, int l
)
299 #ifdef LEAK_DEBUG_LIST
300 struct alloc_header
*ah
= (struct alloc_header
*)((char *)p
- L_D_S
);
301 if (ah
->comment
) free(ah
->comment
);
302 if ((ah
->comment
= malloc(l
+ 1))) memcpy(ah
->comment
, c
, l
), ah
->comment
[l
] = 0;