1 /*************************************************************************/
2 /*                                                                       */
3 /*                  Language Technologies Institute                      */
4 /*                     Carnegie Mellon University                        */
5 /*                        Copyright (c) 1999                             */
6 /*                        All Rights Reserved.                           */
7 /*                                                                       */
8 /*  Permission is hereby granted, free of charge, to use and distribute  */
9 /*  this software and its documentation without restriction, including   */
10 /*  without limitation the rights to use, copy, modify, merge, publish,  */
11 /*  distribute, sublicense, and/or sell copies of this work, and to      */
12 /*  permit persons to whom this work is furnished to do so, subject to   */
13 /*  the following conditions:                                            */
14 /*   1. The code must retain the above copyright notice, this list of    */
15 /*      conditions and the following disclaimer.                         */
16 /*   2. Any modifications must be clearly marked as such.                */
17 /*   3. Original authors' names are not deleted.                         */
18 /*   4. The authors' names are not used to endorse or promote products   */
19 /*      derived from this software without specific prior written        */
20 /*      permission.                                                      */
21 /*                                                                       */
22 /*  CARNEGIE MELLON UNIVERSITY AND THE CONTRIBUTORS TO THIS WORK         */
23 /*  DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING      */
24 /*  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT   */
25 /*  SHALL CARNEGIE MELLON UNIVERSITY NOR THE CONTRIBUTORS BE LIABLE      */
26 /*  FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES    */
27 /*  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN   */
28 /*  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,          */
29 /*  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF       */
30 /*  THIS SOFTWARE.                                                       */
31 /*                                                                       */
32 /*************************************************************************/
33 /*             Author:  Alan W Black (awb@cs.cmu.edu)                    */
34 /*               Date:  July 1999                                        */
35 /*************************************************************************/
36 /*                                                                       */
37 /*  Basic wraparounds for malloc and free                                */
38 /*                                                                       */
39 /*************************************************************************/
40 #include "cst_file.h"
41 #include "cst_alloc.h"
42 #include "cst_error.h"
43 
44 #ifdef UNDER_CE
45 #include <windows.h>
46 #endif /* UNDER_CE */
47 
48 /* define this if you want to trace memory usage */
49 /* #define CST_DEBUG_MALLOC */
50 /* #define CST_DEBUG_MALLOC_TRACE */
51 #ifdef CST_DEBUG_MALLOC
52 int cst_allocated = 0;
53 int cst_freed = 0;
54 int cst_alloc_max = 0;
55 int cst_alloc_imax = 0;
56 int cst_alloc_num_calls = 0;
57 int cst_alloc_out = 0;
58 #ifdef CST_DEBUG_MALLOC_TRACE
59 /* This is a crude memory tracer to find leaks */
60 int cst_alloc_ckpt = -1;
61 /* You have to know how big this should be to use it, its for debuging only */
62 #define NUM_CHUNKS 10000000
63 void *cst_alloc_cunks[NUM_CHUNKS];
64 #endif
65 #endif
66 
cst_safe_alloc(int size)67 void *cst_safe_alloc(int size)
68 {
69     /* returns pointer to memory all set 0 */
70     void *p = NULL;
71     if (size < 0)
72     {
73 	cst_errmsg("alloc: asked for negative size %d\n", size);
74 	cst_error();
75     }
76     else if (size == 0)  /* some mallocs return NULL for this */
77 	size++;
78 
79 #ifdef CST_DEBUG_MALLOC
80     if (size > cst_alloc_imax)
81     {
82 	cst_alloc_imax = size;
83     }
84     cst_allocated += size;
85     cst_alloc_out += size;
86     size += 2 * sizeof(int);
87 #endif
88 
89 #ifdef UNDER_CE
90     p = (void *)LocalAlloc(LPTR, size);
91 #else
92     p = (void *)calloc(size,1);
93 #endif
94 
95 #ifdef CST_DEBUG_MALLOC
96 #ifdef CST_DEBUG_MALLOC_TRACE
97     if (cst_alloc_num_calls == cst_alloc_ckpt)
98 	cst_dbgmsg("cst_malloc: %d\n", cst_alloc_ckpt);
99     cst_alloc_cunks[cst_alloc_num_calls] = p;
100 #endif
101     cst_alloc_num_calls++;
102     *(int *)p = 1314;
103     p = (int *)p + 1;
104     *(int *)p = size - (2 * sizeof(int));
105     if ((cst_allocated - cst_freed) > cst_alloc_max)
106 	cst_alloc_max = cst_allocated - cst_freed;
107     p = (int *)p + 1;
108 #endif
109 
110     if (p == NULL)
111     {
112 	cst_errmsg("alloc: can't alloc %d bytes\n", size);
113 	cst_error();
114     }
115 
116     return p;
117 }
118 
cst_safe_calloc(int size)119 void *cst_safe_calloc(int size)
120 {
121     return cst_safe_alloc(size);
122 }
123 
cst_safe_realloc(void * p,int size)124 void *cst_safe_realloc(void *p,int size)
125 {
126     void *np=0;
127 
128 #ifdef CST_DEBUG_MALLOC
129     cst_free(p);
130     return cst_safe_alloc(size);
131 #endif
132 
133     if (size == 0)
134 	size++;  /* as some mallocs do strange things with 0 */
135 
136     if (p == NULL)
137 	np = cst_safe_alloc(size);
138     else
139 #ifdef UNDER_CE
140 	np = LocalReAlloc((HLOCAL)p, size, LMEM_MOVEABLE|LMEM_ZEROINIT);
141 #else
142 	np = realloc(p,size);
143 #endif
144 
145     if (np == NULL)
146     {
147 	cst_errmsg("CST_REALLOC failed for %d bytes\n",size);
148 	cst_error();
149     }
150 
151     return np;
152 }
153 
cst_free(void * p)154 void cst_free(void *p)
155 {
156     if (p != NULL)
157     {
158 #ifdef CST_DEBUG_MALLOC
159 	if (*((int *)p - 2) != 1314)
160 	{
161 	    cst_dbgmsg("CST_MALLOC_DEBUG freeing non-malloc memory\n");
162 	    return;
163 	}
164 	if (*((int *)p - 1) <= 0)
165 	{
166 	    cst_dbgmsg("CST_MALLOC_DEBUG re-freeing memory\n");
167 	    return;
168 	}
169 	cst_freed += *((int *)p - 1);
170 	cst_alloc_out -= *((int *)p - 1);
171 	*((int *)p - 1) = 0; /* mark it as freed */
172 	p = (int *)p - 2;
173 #endif
174 #ifndef CST_DEBUG_MALLOC_TRACE
175 #ifdef UNDER_CE
176 	if (LocalFree(p) != NULL)
177 	{
178 	    cst_errmsg("LocalFree(%p) failed with code %x\n",
179 		       p, GetLastError());
180 	    cst_error();
181 	}
182 #else
183 	free(p);
184 #endif
185 #endif
186     }
187 }
188 
189 #ifdef CST_DEBUG_MALLOC_TRACE
190 
cst_find_unfreed()191 void cst_find_unfreed()
192 {
193     int i, t;
194 
195 
196     for (i = 0, t = 0;
197 	 i < NUM_CHUNKS
198 	     && i < cst_alloc_num_calls
199 	     && cst_alloc_cunks[i];
200 	 i++)
201     {
202 	if (((int *)cst_alloc_cunks[i])[1] != 0)
203 	{
204             cst_dbgmsg("unfreed at %d\n", i);
205 	    t++;
206 	}
207     }
208     cst_dbgmsg("total unfreed %d\n", t);
209 }
210 
cst_alloc_debug_summary()211 void cst_alloc_debug_summary()
212 {
213     cst_find_unfreed();
214     printf("allocated %d freed %d max %d imax %d calls %d out %d\n",
215 	   cst_allocated, cst_freed, cst_alloc_max,
216 	   cst_alloc_imax, cst_alloc_num_calls, cst_alloc_out);
217 }
218 #endif
219 
220 #ifdef UNDER_CE
new_alloc_context(int size)221 cst_alloc_context new_alloc_context(int size)
222 {
223     HANDLE h;
224 
225     h = HeapCreate(0, size, 0);
226     return (cst_alloc_context) h;
227 }
228 
delete_alloc_context(cst_alloc_context ctx)229 void delete_alloc_context(cst_alloc_context ctx)
230 {
231     HANDLE h;
232 
233     h = (HANDLE)ctx;
234     HeapDestroy(h);
235 }
236 
cst_local_alloc(cst_alloc_context ctx,int size)237 void *cst_local_alloc(cst_alloc_context ctx, int size)
238 {
239     HANDLE h;
240 
241     h = (HANDLE)ctx;
242     if (h)
243 	return HeapAlloc(h, HEAP_ZERO_MEMORY, size);
244     else
245 	return LocalAlloc(LPTR, size);
246 }
247 
cst_local_free(cst_alloc_context ctx,void * p)248 void cst_local_free(cst_alloc_context ctx, void *p)
249 {
250     HANDLE h;
251 
252     h = (HANDLE)ctx;
253     if (h)
254 	HeapFree(h, 0, p);
255     else
256 	LocalFree(p);
257 }
258 #endif
259 
260 
261