comments updated
[henge/apc.git] / stb / stb_leakcheck.h
1 // stb_leakcheck.h - v0.3 - quick & dirty malloc leak-checking - public domain
2 // LICENSE
3 //
4 // This software is dual-licensed to the public domain and under the following
5 // license: you are granted a perpetual, irrevocable license to copy, modify,
6 // publish, and distribute this file as you see fit.
7
8 #ifdef STB_LEAKCHECK_IMPLEMENTATION
9 #undef STB_LEAKCHECK_IMPLEMENTATION // don't implement more than once
10
11 // if we've already included leakcheck before, undefine the macros
12 #ifdef malloc
13 #undef malloc
14 #undef free
15 #undef realloc
16 #endif
17
18 #include <assert.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <stddef.h>
23 typedef struct malloc_info stb_leakcheck_malloc_info;
24
25 struct malloc_info
26 {
27 char *file;
28 int line;
29 size_t size;
30 stb_leakcheck_malloc_info *next,*prev;
31 };
32
33 static stb_leakcheck_malloc_info *mi_head;
34
35 void *stb_leakcheck_malloc(size_t sz, char *file, int line)
36 {
37 stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) malloc(sz + sizeof(*mi));
38 if (mi == NULL) return mi;
39 mi->file = file;
40 mi->line = line;
41 mi->next = mi_head;
42 if (mi_head)
43 mi->next->prev = mi;
44 mi->prev = NULL;
45 mi->size = (int) sz;
46 mi_head = mi;
47 return mi+1;
48 }
49
50 void stb_leakcheck_free(void *ptr)
51 {
52 if (ptr != NULL) {
53 stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) ptr - 1;
54 mi->size = ~mi->size;
55 #ifndef STB_LEAKCHECK_SHOWALL
56 if (mi->prev == NULL) {
57 assert(mi_head == mi);
58 mi_head = mi->next;
59 } else
60 mi->prev->next = mi->next;
61 if (mi->next)
62 mi->next->prev = mi->prev;
63 #endif
64 }
65 }
66
67 void *stb_leakcheck_realloc(void *ptr, size_t sz, char *file, int line)
68 {
69 if (ptr == NULL) {
70 return stb_leakcheck_malloc(sz, file, line);
71 } else if (sz == 0) {
72 stb_leakcheck_free(ptr);
73 return NULL;
74 } else {
75 stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) ptr - 1;
76 if (sz <= mi->size)
77 return ptr;
78 else {
79 #ifdef STB_LEAKCHECK_REALLOC_PRESERVE_MALLOC_FILELINE
80 void *q = stb_leakcheck_malloc(sz, mi->file, mi->line);
81 #else
82 void *q = stb_leakcheck_malloc(sz, file, line);
83 #endif
84 if (q) {
85 memcpy(q, ptr, mi->size);
86 stb_leakcheck_free(ptr);
87 }
88 return q;
89 }
90 }
91 }
92
93 void stb_leakcheck_dumpmem(void)
94 {
95 stb_leakcheck_malloc_info *mi = mi_head;
96 while (mi) {
97 if ((ptrdiff_t) mi->size >= 0)
98 printf("LEAKED: %s (%4d): %8d bytes at %p\n", mi->file, mi->line, (int) mi->size, mi+1);
99 mi = mi->next;
100 }
101 #ifdef STB_LEAKCHECK_SHOWALL
102 mi = mi_head;
103 while (mi) {
104 if ((ptrdiff_t) mi->size < 0)
105 printf("FREED : %s (%4d): %8d bytes at %p\n", mi->file, mi->line, (int) ~mi->size, mi+1);
106 mi = mi->next;
107 }
108 #endif
109 }
110 #endif // STB_LEAKCHECK_IMPLEMENTATION
111
112 #ifndef INCLUDE_STB_LEAKCHECK_H
113 #define INCLUDE_STB_LEAKCHECK_H
114
115 #define malloc(sz) stb_leakcheck_malloc(sz, __FILE__, __LINE__)
116 #define free(p) stb_leakcheck_free(p)
117 #define realloc(p,sz) stb_leakcheck_realloc(p,sz, __FILE__, __LINE__)
118
119 extern void * stb_leakcheck_malloc(size_t sz, char *file, int line);
120 extern void * stb_leakcheck_realloc(void *ptr, size_t sz, char *file, int line);
121 extern void stb_leakcheck_free(void *ptr);
122 extern void stb_leakcheck_dumpmem(void);
123
124 #endif // INCLUDE_STB_LEAKCHECK_H