1 |
johnpye |
938 |
/* ASCEND modelling environment |
2 |
|
|
Copyright (C) 2006 Carnegie Mellon University |
3 |
aw0a |
1 |
|
4 |
johnpye |
938 |
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, or (at your option) |
7 |
|
|
any later version. |
8 |
|
|
|
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. |
13 |
|
|
|
14 |
|
|
You should have received a copy of the GNU General Public License |
15 |
jpye |
2648 |
along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 |
johnpye |
938 |
*//* |
17 |
|
|
Ascend Memory Allocation Routines |
18 |
|
|
by Tom Epperly |
19 |
|
|
Created: 2/6/90 |
20 |
|
|
Last in CVS: $Revision: 1.1 $ $Date: 1997/07/18 11:44:49 $ $Author: mthomas $ |
21 |
|
|
*/ |
22 |
|
|
|
23 |
aw0a |
1 |
#include <stdio.h> |
24 |
|
|
#include <limits.h> |
25 |
johnpye |
908 |
/* if threading, need to make some macros to use the _r functions of time. */ |
26 |
aw0a |
1 |
#include <time.h> |
27 |
|
|
#include <stdlib.h> |
28 |
jds |
99 |
#include <sys/types.h> |
29 |
|
|
#include <sys/stat.h> |
30 |
jds |
97 |
#include <fcntl.h> |
31 |
|
|
#ifndef __WIN32__ |
32 |
|
|
# include <unistd.h> |
33 |
|
|
#else |
34 |
|
|
# include <io.h> /* _open() declared here in MSVC */ |
35 |
|
|
#endif |
36 |
jpye |
2323 |
#include "panic.h" |
37 |
johnpye |
399 |
#include "ascMalloc.h" |
38 |
aw0a |
1 |
|
39 |
jds |
59 |
/* |
40 |
|
|
* The "non-debug" version of ascstrdupf - |
41 |
|
|
* all memory calls should be to the system versions. |
42 |
|
|
*/ |
43 |
johnpye |
1222 |
char *ascstrdupf(CONST char *s){ |
44 |
ben.allan |
16 |
char *result; |
45 |
jds |
59 |
|
46 |
johnpye |
1222 |
if(s == NULL){ |
47 |
|
|
return NULL; |
48 |
|
|
} |
49 |
|
|
|
50 |
|
|
result = ASC_NEW_ARRAY(char,strlen(s) + 1); |
51 |
|
|
|
52 |
|
|
if(result != NULL){ |
53 |
|
|
strcpy(result, s); |
54 |
|
|
} |
55 |
ben.allan |
16 |
return result; |
56 |
|
|
} |
57 |
|
|
|
58 |
johnpye |
939 |
/*------------------------------------------------------------------------------ |
59 |
|
|
ASCEND 'MALLOC' IMPLEMENTATION |
60 |
jds |
59 |
|
61 |
jpye |
2526 |
if 'dmalloc' is being used, we don't need *any* of this stuff |
62 |
johnpye |
939 |
*/ |
63 |
|
|
#ifndef ASC_WITH_DMALLOC |
64 |
|
|
|
65 |
|
|
#define MAXPOINTERS 1000000 |
66 |
|
|
|
67 |
|
|
/* temporary file support */ |
68 |
|
|
#ifdef __WIN32__ |
69 |
|
|
# define LOGFILE "memlg" |
70 |
|
|
#else |
71 |
|
|
# define TEMPFILE_TEMPLATE "/tmp/ascmemlog_XXXXXX" |
72 |
|
|
#endif |
73 |
|
|
|
74 |
|
|
|
75 |
|
|
|
76 |
|
|
|
77 |
jds |
59 |
/* |
78 |
johnpye |
1220 |
* Here's the debug version of ASC_STRDUP - |
79 |
jds |
59 |
* all memory calls should be to the local debug versions. |
80 |
|
|
*/ |
81 |
johnpye |
938 |
char *ascstrdupf_dbg(CONST char *s){ |
82 |
jds |
59 |
char *result; |
83 |
|
|
|
84 |
|
|
if (NULL == s) { |
85 |
johnpye |
938 |
return NULL; |
86 |
|
|
} |
87 |
jds |
59 |
result = (char *)ascmallocf(strlen(s) + 1, __FILE__, __LINE__); |
88 |
johnpye |
938 |
if (NULL != result) { |
89 |
|
|
strcpy(result, s); |
90 |
|
|
} |
91 |
jds |
59 |
return result; |
92 |
|
|
} |
93 |
|
|
|
94 |
johnpye |
938 |
char *asc_memcpy(char *to, char *from, size_t size){ |
95 |
aw0a |
1 |
/* We really should be moving stuff a long at a time, but that mean |
96 |
|
|
* handling the leading and trailing unaligned bytes separately. |
97 |
|
|
* We also really should just be passing on to the vendor memcpy on |
98 |
|
|
* those systems which do overlapping ranges right. |
99 |
|
|
*/ |
100 |
|
|
char *fill; |
101 |
jds |
97 |
asc_assert((size == 0) || ((NULL != to) && (NULL != from))); |
102 |
aw0a |
1 |
if (from < to) { |
103 |
|
|
fill = (to + size) - 1; |
104 |
|
|
from += (size - 1); |
105 |
|
|
while (size-- > 0) { |
106 |
|
|
*fill-- = *from--; |
107 |
|
|
} |
108 |
johnpye |
938 |
}else{ |
109 |
aw0a |
1 |
if (from > to) { |
110 |
|
|
fill = to; |
111 |
|
|
while (size-- > 0) { |
112 |
|
|
*fill++ = *from++; |
113 |
|
|
} |
114 |
|
|
} /* else from == to, do nothing */ |
115 |
|
|
} |
116 |
|
|
return to; |
117 |
|
|
} |
118 |
|
|
|
119 |
jds |
59 |
/* |
120 |
|
|
* The "non-debug" version of ascreallocPURE - |
121 |
|
|
* all memory calls should be to the system versions. |
122 |
|
|
*/ |
123 |
|
|
char *ascreallocPUREF(char *ptr, size_t oldbytes, size_t newbytes) |
124 |
aw0a |
1 |
{ |
125 |
|
|
/* shrink */ |
126 |
|
|
if (newbytes > 0 && newbytes <= oldbytes) return ptr; |
127 |
|
|
/* release */ |
128 |
|
|
if (!newbytes) { |
129 |
jds |
59 |
free(ptr); |
130 |
aw0a |
1 |
return NULL; |
131 |
|
|
} |
132 |
|
|
/* create */ |
133 |
|
|
if (!oldbytes) { |
134 |
jds |
59 |
if (ptr!=NULL) free(ptr); /* some OS allocate 0 bytes, god help us */ |
135 |
|
|
return (char *)malloc(newbytes); |
136 |
johnpye |
938 |
}else{ |
137 |
aw0a |
1 |
/* expand */ |
138 |
|
|
char *ret; |
139 |
jds |
59 |
ret = malloc(newbytes); |
140 |
aw0a |
1 |
if (ret==NULL) return NULL; |
141 |
jpye |
2526 |
if (oldbytes%sizeof(long) == 0 && ((asc_intptr_t)ptr)%sizeof(long) == 0) { |
142 |
aw0a |
1 |
register unsigned long c,len, *src, *trg; |
143 |
|
|
src = (unsigned long *)ptr; |
144 |
|
|
trg = (unsigned long *)ret; |
145 |
|
|
len = oldbytes/sizeof(long); |
146 |
|
|
for (c=0;c < len;c++) trg[c]=src[c]; /* copy data as longs */ |
147 |
|
|
} else { |
148 |
|
|
memcpy(ret,ptr,oldbytes); |
149 |
|
|
} |
150 |
jds |
59 |
free(ptr); |
151 |
aw0a |
1 |
return ret; |
152 |
|
|
} |
153 |
|
|
} |
154 |
jds |
59 |
|
155 |
|
|
/* |
156 |
|
|
* Here's the debug version of ascreallocPURE - |
157 |
|
|
* all memory calls should be to the local debug versions. |
158 |
|
|
*/ |
159 |
|
|
char *ascreallocPUREF_dbg(char *ptr, size_t oldbytes, size_t newbytes) |
160 |
|
|
{ |
161 |
|
|
/* shrink */ |
162 |
|
|
if (newbytes > 0 && newbytes <= oldbytes) return ptr; |
163 |
|
|
/* release */ |
164 |
|
|
if (!newbytes) { |
165 |
|
|
ascfreef(ptr, __FILE__, __LINE__); |
166 |
|
|
return NULL; |
167 |
|
|
} |
168 |
|
|
/* create */ |
169 |
|
|
if (!oldbytes) { |
170 |
|
|
if (ptr!=NULL) ascfreef(ptr, __FILE__, __LINE__); /* some OS allocate 0 bytes, god help us */ |
171 |
|
|
return (char *)ascmallocf(newbytes, __FILE__, __LINE__); |
172 |
johnpye |
938 |
}else{ |
173 |
jds |
59 |
/* expand */ |
174 |
|
|
char *ret; |
175 |
|
|
ret = ascmallocf(newbytes, __FILE__, __LINE__); |
176 |
|
|
if (ret==NULL) return NULL; |
177 |
jpye |
2526 |
if (oldbytes%sizeof(long) == 0 && ((asc_intptr_t)ptr)%sizeof(long) == 0) { |
178 |
jds |
59 |
register unsigned long c,len, *src, *trg; |
179 |
|
|
src = (unsigned long *)ptr; |
180 |
|
|
trg = (unsigned long *)ret; |
181 |
|
|
len = oldbytes/sizeof(long); |
182 |
|
|
for (c=0;c < len;c++) trg[c]=src[c]; /* copy data as longs */ |
183 |
|
|
} else { |
184 |
|
|
memcpy(ret,ptr,oldbytes); |
185 |
|
|
} |
186 |
|
|
ascfreef(ptr, __FILE__, __LINE__); |
187 |
|
|
return ret; |
188 |
|
|
} |
189 |
|
|
} |
190 |
|
|
|
191 |
aw0a |
1 |
struct memory_rec{ |
192 |
|
|
CONST VOIDPTR ptr; |
193 |
jds |
59 |
size_t size; |
194 |
aw0a |
1 |
}; |
195 |
|
|
|
196 |
jds |
97 |
#ifdef __WIN32__ |
197 |
|
|
static char *f_memlog_filename = NULL; |
198 |
|
|
#endif |
199 |
|
|
static FILE *f_memory_log_file = NULL; |
200 |
|
|
static int f_memory_length = 0; |
201 |
|
|
static unsigned long f_memory_allocated = 0L; |
202 |
|
|
static unsigned long f_peak_memory_usage = 0L; |
203 |
|
|
static struct memory_rec f_mem_rec[MAXPOINTERS]; |
204 |
aw0a |
1 |
|
205 |
jds |
59 |
unsigned long ascmeminusef(void) |
206 |
aw0a |
1 |
{ |
207 |
jds |
97 |
return f_memory_allocated; |
208 |
aw0a |
1 |
} |
209 |
|
|
|
210 |
jds |
59 |
static CONST VOIDPTR MinMemory(void) |
211 |
aw0a |
1 |
{ |
212 |
|
|
int c; |
213 |
|
|
CONST VOIDPTR minm=(VOIDPTR)ULONG_MAX; |
214 |
jds |
97 |
for(c=0;c<f_memory_length;c++) |
215 |
|
|
if (f_mem_rec[c].ptr < minm) minm = f_mem_rec[c].ptr; |
216 |
aw0a |
1 |
return minm; |
217 |
|
|
} |
218 |
|
|
|
219 |
jds |
59 |
static CONST VOIDPTR MaxMemory(void) |
220 |
aw0a |
1 |
{ |
221 |
|
|
int c; |
222 |
|
|
CONST VOIDPTR maxm=0; |
223 |
jds |
97 |
for(c=0;c<f_memory_length;c++) |
224 |
|
|
if (((CONST char *)f_mem_rec[c].ptr + f_mem_rec[c].size - 1) |
225 |
jds |
59 |
> (CONST char *)maxm) |
226 |
jds |
97 |
maxm = (CONST VOIDPTR)((CONST char *)f_mem_rec[c].ptr + f_mem_rec[c].size - 1); |
227 |
aw0a |
1 |
return maxm; |
228 |
|
|
} |
229 |
|
|
|
230 |
jds |
59 |
#define NONZERO(x) ((0 != (x)) ? (x) : 1) |
231 |
aw0a |
1 |
|
232 |
jds |
59 |
static CONST VOIDPTR MemoryMean(void) |
233 |
aw0a |
1 |
{ |
234 |
jds |
59 |
int c; |
235 |
|
|
size_t size; |
236 |
|
|
double sum=0.0, bytes=0.0; |
237 |
jds |
97 |
for(c=0 ; c<f_memory_length ; c++){ |
238 |
|
|
size = f_mem_rec[c].size; |
239 |
jds |
59 |
if (0 != size){ |
240 |
aw0a |
1 |
bytes += (double)size; |
241 |
|
|
sum += (double)((size * (size-1))/2) |
242 |
jpye |
2526 |
+ ((double)size) * ((double)(asc_intptr_t)f_mem_rec[c].ptr); |
243 |
aw0a |
1 |
} |
244 |
|
|
} |
245 |
jpye |
2526 |
return (VOIDPTR)(asc_intptr_t)(sum/NONZERO(bytes)); |
246 |
aw0a |
1 |
} |
247 |
|
|
|
248 |
jds |
59 |
/* |
249 |
jds |
97 |
* Creates a temporary file for logging memory events. |
250 |
jds |
59 |
* The file is opened and header information is written to it. |
251 |
jds |
100 |
* Thereafter, the FILE* is available to other routines in |
252 |
|
|
* f_memory_log_file, which should append to the file as needed. |
253 |
jds |
97 |
* This function may be called more than once - the file will only be |
254 |
jds |
100 |
* created and header info written the first time it is called, or |
255 |
jds |
97 |
* after ascshutdown() has been called. |
256 |
jds |
59 |
*/ |
257 |
|
|
static void OpenLogFile(void) |
258 |
aw0a |
1 |
{ |
259 |
johnpye |
67 |
time_t t; |
260 |
jds |
100 |
int handle; |
261 |
|
|
|
262 |
|
|
if (NULL == f_memory_log_file) { |
263 |
|
|
|
264 |
jds |
97 |
#ifdef __WIN32__ |
265 |
|
|
/* Windows doesn't have mkstemp(), so need to use tempnam() */ |
266 |
|
|
f_memlog_filename = tempnam(NULL, LOGFILE); |
267 |
|
|
if (NULL == f_memlog_filename) { |
268 |
johnpye |
1064 |
ASC_PANIC("Unable to create a unique memory log filename.\n"); |
269 |
jds |
97 |
} |
270 |
|
|
handle = _open(f_memlog_filename, |
271 |
|
|
O_WRONLY | O_CREAT | O_EXCL | O_TEXT, |
272 |
|
|
_S_IREAD | _S_IWRITE); |
273 |
|
|
if ((-1 == handle) || |
274 |
jds |
216 |
(NULL == (f_memory_log_file = fdopen(handle,"w")))) { |
275 |
johnpye |
1064 |
ASC_PANIC("Unable to open memory log file.\n"); |
276 |
jds |
100 |
} |
277 |
jds |
97 |
#else |
278 |
jds |
100 |
char temp_filename[] = TEMPFILE_TEMPLATE; |
279 |
|
|
handle = mkstemp(temp_filename); |
280 |
|
|
if ((-1 == handle) || |
281 |
|
|
(NULL == (f_memory_log_file = fdopen(handle,"r+")))) { |
282 |
johnpye |
1064 |
ASC_PANIC("Unable to open memory log file.\n"); |
283 |
jds |
100 |
} |
284 |
jds |
97 |
#endif /* __WIN32__ */ |
285 |
jds |
100 |
|
286 |
|
|
t = time((time_t *)NULL); |
287 |
jds |
97 |
FPRINTF(f_memory_log_file,"Ascend memory log file opened %s", |
288 |
johnpye |
67 |
asctime(localtime(&t))); |
289 |
jds |
97 |
FPRINTF(f_memory_log_file,"%16s %13s %16s %13s %6s %s", |
290 |
johnpye |
67 |
"Alloc Range", |
291 |
|
|
"Size", |
292 |
|
|
"Dealloc Range", |
293 |
|
|
"Size", |
294 |
|
|
"Line#", |
295 |
|
|
"Source File\n"); |
296 |
jds |
97 |
fflush(f_memory_log_file); |
297 |
jds |
100 |
} |
298 |
aw0a |
1 |
} |
299 |
|
|
|
300 |
jpye |
3199 |
static void WriteMemoryStatus(FILE *f, CONST char *msg){ |
301 |
|
|
CONST VOIDPTR minm; |
302 |
|
|
CONST VOIDPTR maxm; |
303 |
|
|
minm = MinMemory(); |
304 |
|
|
maxm = MaxMemory(); |
305 |
|
|
ASC_FPRINTF(f,"%s\n" |
306 |
|
|
"Current memory usage(byte allocated): %lu\n" |
307 |
|
|
"Current number of blocks: %d\n" |
308 |
|
|
"Peak memory usage(bytes allocated): %lu\n" |
309 |
|
|
"Lowest address: %lx\n" |
310 |
|
|
"Highest address: %lx\n" |
311 |
|
|
"Memory density: %g\n" |
312 |
|
|
"Memory mean: %lx\n", |
313 |
|
|
msg, |
314 |
|
|
f_memory_allocated, |
315 |
|
|
f_memory_length, |
316 |
|
|
f_peak_memory_usage, |
317 |
|
|
(asc_intptr_t)minm, |
318 |
|
|
(asc_intptr_t)maxm, |
319 |
|
|
((double)f_memory_allocated/(double) |
320 |
|
|
NONZERO((CONST char *)maxm - (CONST char *)minm)), |
321 |
|
|
(asc_intptr_t)MemoryMean() |
322 |
|
|
); |
323 |
aw0a |
1 |
} |
324 |
|
|
|
325 |
jds |
59 |
static void WriteMemoryRecords(FILE *f, CONST char *msg) |
326 |
aw0a |
1 |
{ |
327 |
jds |
59 |
int c; |
328 |
jpye |
3199 |
ASC_FPRINTF(f,"%s\nAllocation record count: %d\n", msg, f_memory_length); |
329 |
jds |
97 |
for (c=0 ; c<f_memory_length ; ++c) { |
330 |
jpye |
3215 |
ASC_FPRINTF(f,"%5d %p->%p %9zu\n", |
331 |
jds |
59 |
c, |
332 |
jds |
97 |
f_mem_rec[c].ptr, |
333 |
|
|
(CONST VOIDPTR)((CONST char *)f_mem_rec[c].ptr + f_mem_rec[c].size), |
334 |
|
|
f_mem_rec[c].size); |
335 |
jds |
59 |
} |
336 |
|
|
} |
337 |
|
|
|
338 |
|
|
void ascstatusf(CONST char *msg) |
339 |
|
|
{ |
340 |
aw0a |
1 |
OpenLogFile(); |
341 |
jds |
97 |
if (NULL != f_memory_log_file) { |
342 |
|
|
WriteMemoryStatus(f_memory_log_file, msg); |
343 |
|
|
fflush(f_memory_log_file); |
344 |
aw0a |
1 |
} |
345 |
jds |
97 |
WriteMemoryStatus(ASCINF, msg); |
346 |
aw0a |
1 |
} |
347 |
|
|
|
348 |
jds |
59 |
void ascstatus_detailf(CONST char *msg) |
349 |
aw0a |
1 |
{ |
350 |
|
|
OpenLogFile(); |
351 |
jds |
97 |
if (NULL != f_memory_log_file) { |
352 |
|
|
WriteMemoryStatus(f_memory_log_file, msg); |
353 |
|
|
WriteMemoryRecords(f_memory_log_file, "\nDetail Report of Currently Allocated Blocks"); |
354 |
|
|
fflush(f_memory_log_file); |
355 |
jds |
59 |
} |
356 |
jds |
97 |
WriteMemoryStatus(ASCINF, msg); |
357 |
|
|
WriteMemoryRecords(ASCINF, "\nDetail Report of Currently Allocated Blocks"); |
358 |
jds |
59 |
} |
359 |
|
|
|
360 |
jpye |
3199 |
void ascshutdownf(CONST char *msg){ |
361 |
jds |
59 |
OpenLogFile(); |
362 |
jpye |
3199 |
if(NULL != f_memory_log_file) { |
363 |
|
|
//CONSOLE_DEBUG("got a memory log file %p",f_memory_log_file); |
364 |
jds |
97 |
WriteMemoryStatus(f_memory_log_file,msg); |
365 |
jpye |
3199 |
if(f_memory_length){ |
366 |
jds |
97 |
WriteMemoryRecords(f_memory_log_file, "\n!!! SHUTDOWN ALERT -- POINTERS STILL ALLOCATED !!!"); |
367 |
jpye |
3199 |
ASC_FPRINTF(f_memory_log_file, "!!! END OF SHUTDOWN MESSAGE !!!\n"); |
368 |
aw0a |
1 |
} else { |
369 |
jpye |
3199 |
ASC_FPRINTF(f_memory_log_file, "NO POINTERS STILL ALLOCATED :-)\n"); |
370 |
aw0a |
1 |
} |
371 |
jds |
97 |
fflush(f_memory_log_file); |
372 |
|
|
#ifdef __WIN32__ |
373 |
jpye |
3199 |
CONSOLE_DEBUG("Memory log written to: %s", f_memlog_filename); |
374 |
jds |
97 |
free(f_memlog_filename); /* free(), NOT ascfree() */ |
375 |
|
|
f_memlog_filename = NULL; |
376 |
|
|
#else |
377 |
jpye |
3199 |
CONSOLE_DEBUG("Memory log file written & closed."); |
378 |
jds |
97 |
#endif |
379 |
|
|
fclose(f_memory_log_file); |
380 |
|
|
f_memory_log_file = NULL; |
381 |
aw0a |
1 |
} |
382 |
jds |
97 |
WriteMemoryStatus(ASCINF, msg); |
383 |
jpye |
3199 |
if(f_memory_length){ |
384 |
jds |
97 |
WriteMemoryRecords(ASCINF, "\n!!! SHUTDOWN ALERT -- POINTERS STILL ALLOCATED !!!"); |
385 |
jpye |
3199 |
ASC_FPRINTF(ASCINF, "!!! END OF SHUTDOWN MESSAGE !!!\n"); |
386 |
jds |
59 |
} else { |
387 |
jpye |
3199 |
ASC_FPRINTF(ASCINF, "NO POINTERS STILL ALLOCATED :-)\n"); |
388 |
jds |
59 |
} |
389 |
aw0a |
1 |
} |
390 |
|
|
|
391 |
jds |
59 |
static void WriteAllocation(CONST VOIDPTR adr, size_t size, |
392 |
|
|
CONST char *file, int line) |
393 |
aw0a |
1 |
{ |
394 |
jds |
97 |
if (NULL != f_memory_log_file) { |
395 |
jpye |
3215 |
ASC_FPRINTF(f_memory_log_file,"%p->%p %9zu %31s%6d %s\n", |
396 |
|
|
adr, |
397 |
|
|
adr + size - 1, |
398 |
jds |
59 |
size, |
399 |
|
|
"", |
400 |
|
|
line, |
401 |
|
|
file); |
402 |
jds |
97 |
fflush(f_memory_log_file); |
403 |
aw0a |
1 |
} |
404 |
|
|
else{ |
405 |
jpye |
3199 |
ASC_FPRINTF(ASCERR,"Unable to append to memory log file.\n"); |
406 |
jpye |
3215 |
ASC_FPRINTF(ASCERR,"%p->%p %9zu %31s%6d %s\n", |
407 |
|
|
adr, |
408 |
|
|
adr + size - 1, |
409 |
jds |
59 |
size, |
410 |
|
|
"", |
411 |
|
|
line, |
412 |
|
|
file); |
413 |
aw0a |
1 |
} |
414 |
|
|
} |
415 |
|
|
|
416 |
jds |
59 |
static void WriteReAllocation(CONST VOIDPTR adr1, size_t size1, |
417 |
|
|
CONST VOIDPTR adr2, size_t size2, |
418 |
|
|
CONST char *file, int line) |
419 |
aw0a |
1 |
{ |
420 |
jds |
97 |
if (NULL != f_memory_log_file) { |
421 |
jpye |
3215 |
ASC_FPRINTF(f_memory_log_file,"%p->%p %9zu %p->%p %9zu %6d %s\n", |
422 |
|
|
adr2, |
423 |
|
|
adr2 + size2 - 1, |
424 |
jds |
59 |
size2, |
425 |
jpye |
3215 |
adr1, |
426 |
|
|
adr1 + size1 - 1, |
427 |
jds |
59 |
size1, line, file); |
428 |
jds |
97 |
fflush(f_memory_log_file); |
429 |
aw0a |
1 |
} |
430 |
|
|
else{ |
431 |
jpye |
3199 |
ASC_FPRINTF(ASCERR,"Unable to append to memory log file.\n"); |
432 |
jpye |
3215 |
ASC_FPRINTF(ASCERR,"%p->%p %9zu %p->%p %9zu %6d %s\n", |
433 |
|
|
adr2, |
434 |
|
|
adr2 + size2 - 1, |
435 |
jds |
59 |
size2, |
436 |
jpye |
3215 |
adr1, |
437 |
|
|
adr1 + size1 - 1, |
438 |
jds |
59 |
size1, line, file); |
439 |
aw0a |
1 |
} |
440 |
|
|
} |
441 |
|
|
|
442 |
jds |
59 |
static void WriteDeallocation(CONST VOIDPTR adr, size_t size, |
443 |
|
|
CONST char *file, int line) |
444 |
aw0a |
1 |
{ |
445 |
jds |
97 |
if (NULL != f_memory_log_file) { |
446 |
jpye |
3215 |
ASC_FPRINTF(f_memory_log_file,"%31s%p->%p %9zu %6d %s\n","", |
447 |
|
|
adr, |
448 |
|
|
adr + size - 1, |
449 |
jds |
59 |
size, line, file); |
450 |
jds |
97 |
fflush(f_memory_log_file); |
451 |
aw0a |
1 |
} |
452 |
|
|
else{ |
453 |
jpye |
3199 |
ASC_FPRINTF(ASCERR,"Unable to append to memory log file.\n"); |
454 |
jpye |
3215 |
ASC_FPRINTF(ASCERR,"%31s%p->%p %9zu %6d %s\n","", |
455 |
|
|
adr, |
456 |
|
|
adr + size - 1, |
457 |
jds |
59 |
size, line, file); |
458 |
aw0a |
1 |
} |
459 |
|
|
} |
460 |
|
|
|
461 |
jds |
59 |
static void WriteError(CONST char *msg, CONST char *file, int line) |
462 |
aw0a |
1 |
{ |
463 |
jds |
97 |
FPRINTF(ASCERR,"%s\nCalled from file: %s on line %d.\n", msg, file, line); |
464 |
|
|
if (NULL != f_memory_log_file) { |
465 |
|
|
FPRINTF(f_memory_log_file,"%s\nCalled from file: %s on line %d.\n", |
466 |
jds |
59 |
msg, file, line); |
467 |
jds |
97 |
fflush(f_memory_log_file); |
468 |
aw0a |
1 |
} |
469 |
|
|
} |
470 |
|
|
|
471 |
jds |
59 |
/* |
472 |
|
|
* Searches the array of allocation records for ptr. |
473 |
|
|
* Returns -1 if no memory records have been recorded. |
474 |
|
|
* Otherwise, returns the index of the memory record for |
475 |
|
|
* which the stored pointer is greater than or equal to |
476 |
|
|
* ptr. If ptr is higher than any of the stored pointers, |
477 |
jds |
97 |
* then f_memory_length is returned. |
478 |
jds |
59 |
* |
479 |
|
|
* This routine assumes that the memory record array is sorted |
480 |
|
|
* by pointer address ascending. |
481 |
|
|
*/ |
482 |
|
|
static int SearchForMemory(CONST VOIDPTR ptr) |
483 |
aw0a |
1 |
{ |
484 |
jds |
59 |
int c, lower, upper; |
485 |
|
|
lower = 0; |
486 |
jds |
97 |
upper = f_memory_length-1; |
487 |
jds |
59 |
if (upper<lower) return -1; |
488 |
|
|
while(lower<upper){ |
489 |
|
|
c = (lower+upper)/2; |
490 |
jds |
97 |
if (f_mem_rec[c].ptr == ptr) return c; |
491 |
|
|
if (f_mem_rec[c].ptr > ptr) |
492 |
jds |
59 |
upper = c-1; |
493 |
aw0a |
1 |
else |
494 |
jds |
59 |
lower = c+1; |
495 |
aw0a |
1 |
} |
496 |
jds |
59 |
if (upper<lower) return lower; |
497 |
|
|
if (lower>upper) return upper; |
498 |
jds |
97 |
while(( lower < f_memory_length ) && ( f_mem_rec[lower].ptr < ptr )) lower++; |
499 |
jds |
59 |
return lower; |
500 |
aw0a |
1 |
} |
501 |
|
|
|
502 |
jds |
59 |
int AllocatedMemoryF(CONST VOIDPTR ptr, size_t size) |
503 |
aw0a |
1 |
{ |
504 |
jds |
59 |
int pos; |
505 |
|
|
|
506 |
|
|
if (NULL == ptr) /* NULL ptr - by definition not allocated */ |
507 |
|
|
return 0; |
508 |
|
|
|
509 |
aw0a |
1 |
pos = SearchForMemory(ptr); |
510 |
jds |
59 |
|
511 |
|
|
if (pos < 0) /* no allocation records have been stored */ |
512 |
|
|
return 0; |
513 |
|
|
|
514 |
|
|
/* if a matching pointer was found... */ |
515 |
jds |
97 |
if (( pos < f_memory_length ) && |
516 |
|
|
( f_mem_rec[pos].ptr == ptr )) { |
517 |
|
|
if ( f_mem_rec[pos].size == size ) |
518 |
jds |
59 |
return 2; /* the block matches an allocated block */ |
519 |
jds |
97 |
if ( f_mem_rec[pos].size > size ) |
520 |
jds |
59 |
return 1; /* the block is contained in an allocated block */ |
521 |
|
|
return -1; /* the block spans multiple allocated blocks */ |
522 |
aw0a |
1 |
} |
523 |
jds |
59 |
|
524 |
|
|
/* if ptr block extends into the block above... */ |
525 |
jds |
97 |
else if (( pos < f_memory_length ) && |
526 |
|
|
((CONST VOIDPTR)((CONST char *)ptr + size - 1) >= f_mem_rec[pos].ptr)) { |
527 |
jds |
59 |
return -1; /* the block extends into the block above */ |
528 |
aw0a |
1 |
} |
529 |
jds |
59 |
|
530 |
|
|
else if (pos > 0) { |
531 |
jds |
97 |
if (ptr > ((CONST VOIDPTR)((CONST char *)f_mem_rec[pos-1].ptr + f_mem_rec[pos-1].size - 1))) |
532 |
jds |
59 |
return 0; /* ptr not contained within the found block */ |
533 |
|
|
|
534 |
|
|
if ((CONST VOIDPTR)((CONST char *)ptr + size) |
535 |
jds |
97 |
<= (CONST VOIDPTR)((CONST char *)f_mem_rec[pos-1].ptr + f_mem_rec[pos-1].size)) |
536 |
jds |
59 |
return 1; /* the block is contained in an allocated block */ |
537 |
|
|
else |
538 |
|
|
return -1; /* the block spans multiple allocated blocks */ |
539 |
|
|
} |
540 |
|
|
|
541 |
|
|
return 0; |
542 |
aw0a |
1 |
} |
543 |
|
|
|
544 |
jds |
59 |
static void AddAllocatedMemory(CONST VOIDPTR ptr, size_t size, |
545 |
|
|
CONST char *file, int line) |
546 |
aw0a |
1 |
{ |
547 |
|
|
int pos,c; |
548 |
|
|
pos = SearchForMemory(ptr); |
549 |
jds |
59 |
if (( pos < 0 ) || |
550 |
jds |
97 |
( pos == f_memory_length) || |
551 |
|
|
( f_mem_rec[pos].ptr != ptr )) { |
552 |
jds |
59 |
if ( pos < 0 ) pos = 0; |
553 |
jds |
97 |
if ( (f_memory_length + 1) < MAXPOINTERS ) { |
554 |
|
|
if ( pos == f_memory_length ) { |
555 |
|
|
f_memory_length++; |
556 |
|
|
f_mem_rec[pos].ptr = ptr; |
557 |
|
|
f_mem_rec[pos].size = size; |
558 |
aw0a |
1 |
} |
559 |
jds |
59 |
else { |
560 |
|
|
/* make room for the new addition */ |
561 |
jds |
97 |
for(c=f_memory_length ; c>pos ; c--){ |
562 |
|
|
f_mem_rec[c] = f_mem_rec[c-1]; |
563 |
jds |
59 |
} |
564 |
jds |
97 |
f_memory_length++; |
565 |
|
|
f_mem_rec[pos].ptr = ptr; |
566 |
|
|
f_mem_rec[pos].size = size; |
567 |
aw0a |
1 |
} |
568 |
|
|
} |
569 |
jds |
59 |
else { |
570 |
jds |
97 |
FPRINTF(ASCERR, "Pointer list filled up. Error messages may be unreliable.\n"); |
571 |
aw0a |
1 |
} |
572 |
|
|
} |
573 |
|
|
WriteAllocation(ptr,size,file,line); |
574 |
|
|
} |
575 |
|
|
|
576 |
jds |
59 |
static void DeallocateMemory(CONST VOIDPTR ptr, size_t size, |
577 |
|
|
CONST char *file, int line) |
578 |
aw0a |
1 |
{ |
579 |
|
|
int pos,c; |
580 |
|
|
pos = SearchForMemory(ptr); |
581 |
jpye |
2526 |
if (( pos >= 0 ) && |
582 |
jds |
97 |
( pos < f_memory_length ) && |
583 |
|
|
( f_mem_rec[pos].ptr == ptr )) { |
584 |
jds |
59 |
/* a matching pointer was found */ |
585 |
jds |
97 |
asc_assert(f_mem_rec[pos].size == size); |
586 |
jds |
59 |
/* copy all allocation records to the previous index, overwriting the current record */ |
587 |
jds |
97 |
for(c=pos+1 ; c<f_memory_length ; c++) |
588 |
|
|
f_mem_rec[c-1] = f_mem_rec[c]; |
589 |
|
|
f_memory_length--; |
590 |
aw0a |
1 |
} |
591 |
|
|
WriteDeallocation(ptr,size,file,line); |
592 |
|
|
} |
593 |
|
|
|
594 |
jds |
59 |
static void ReallocateMemory(CONST VOIDPTR ptr1, size_t size1, |
595 |
|
|
CONST VOIDPTR ptr2, size_t size2, |
596 |
|
|
CONST char *file, int line) |
597 |
aw0a |
1 |
{ |
598 |
|
|
int pos,c; |
599 |
jds |
59 |
/* handle the deallocation first */ |
600 |
aw0a |
1 |
pos = SearchForMemory(ptr1); |
601 |
jds |
59 |
if (( pos >= 0 ) && |
602 |
jds |
97 |
( pos < f_memory_length ) && |
603 |
|
|
( f_mem_rec[pos].ptr == ptr1 )) { |
604 |
jds |
59 |
/* a matching pointer was found */ |
605 |
jds |
97 |
asc_assert(f_mem_rec[pos].size == size1); |
606 |
jds |
59 |
/* copy all allocation records to the previous index, overwriting the current record */ |
607 |
jds |
97 |
for(c=pos+1 ; c<f_memory_length ; c++) |
608 |
|
|
f_mem_rec[c-1] = f_mem_rec[c]; |
609 |
|
|
f_memory_length--; |
610 |
aw0a |
1 |
} |
611 |
jds |
59 |
/* then, handle the allocation if ptr2 is non-NULL */ |
612 |
aw0a |
1 |
pos = SearchForMemory(ptr2); |
613 |
jds |
59 |
if (( NULL != ptr2 ) && |
614 |
|
|
(( pos < 0 ) || |
615 |
jds |
97 |
( pos == f_memory_length) || |
616 |
|
|
( f_mem_rec[pos].ptr != ptr2 ))) { |
617 |
jds |
59 |
if ( pos < 0 ) pos = 0; |
618 |
jds |
97 |
if ( (f_memory_length + 1) < MAXPOINTERS ) { |
619 |
|
|
if ( pos == f_memory_length ) { |
620 |
|
|
f_memory_length++; |
621 |
|
|
f_mem_rec[pos].ptr = ptr2; |
622 |
|
|
f_mem_rec[pos].size = size2; |
623 |
aw0a |
1 |
} |
624 |
jds |
59 |
else { |
625 |
|
|
/* make room for the new addition */ |
626 |
jds |
97 |
for(c=f_memory_length ; c>pos ; c--){ |
627 |
|
|
f_mem_rec[c] = f_mem_rec[c-1]; |
628 |
jds |
59 |
} |
629 |
jds |
97 |
f_memory_length++; |
630 |
|
|
f_mem_rec[pos].ptr = ptr2; |
631 |
|
|
f_mem_rec[pos].size = size2; |
632 |
aw0a |
1 |
} |
633 |
|
|
} |
634 |
jds |
59 |
else { |
635 |
jds |
97 |
FPRINTF(ASCERR, "Pointer list filled up. Error messages may be unreliable.\n"); |
636 |
aw0a |
1 |
} |
637 |
|
|
} |
638 |
|
|
WriteReAllocation(ptr1,size1,ptr2,size2,file,line); |
639 |
|
|
} |
640 |
|
|
|
641 |
jds |
59 |
VOIDPTR asccallocf(size_t nelem, size_t elsize, |
642 |
|
|
CONST char *file, int line) |
643 |
aw0a |
1 |
{ |
644 |
|
|
VOIDPTR result; |
645 |
|
|
OpenLogFile(); |
646 |
|
|
result = calloc(nelem,elsize); |
647 |
jds |
59 |
if (NULL != result) { |
648 |
|
|
/* adjust statistical variables */ |
649 |
jds |
97 |
f_memory_allocated += nelem*elsize; |
650 |
|
|
if (f_memory_allocated > f_peak_memory_usage) |
651 |
|
|
f_peak_memory_usage = f_memory_allocated; |
652 |
jds |
59 |
if (AllocatedMemory(result,nelem*elsize)){ |
653 |
|
|
WriteError("calloc returned a piece of memory that is already being used.", |
654 |
|
|
file,line); |
655 |
|
|
} |
656 |
|
|
AddAllocatedMemory(result,nelem*elsize,file,line); |
657 |
aw0a |
1 |
} |
658 |
|
|
return result; |
659 |
|
|
} |
660 |
|
|
|
661 |
jds |
59 |
VOIDPTR ascmallocf(size_t size, CONST char *file, int line) |
662 |
aw0a |
1 |
{ |
663 |
|
|
VOIDPTR result; |
664 |
|
|
OpenLogFile(); |
665 |
|
|
result = malloc(size); |
666 |
jds |
59 |
if (NULL != result) { |
667 |
jds |
97 |
f_memory_allocated += size; |
668 |
|
|
if (f_memory_allocated > f_peak_memory_usage) |
669 |
|
|
f_peak_memory_usage = f_memory_allocated; |
670 |
jds |
59 |
if (AllocatedMemory(result,size)){ |
671 |
|
|
WriteError("malloc returned a piece of memory that is already being used.", |
672 |
|
|
file,line); |
673 |
|
|
} |
674 |
|
|
AddAllocatedMemory(result,size,file,line); |
675 |
johnpye |
62 |
}else{ |
676 |
jpye |
3215 |
ASC_FPRINTF(ASCERR,"ASCMALLOC FAILED TO ALLOCATE MEMORY OF SIZE %zu, result=%p\n",size,result); |
677 |
aw0a |
1 |
} |
678 |
|
|
return result; |
679 |
|
|
} |
680 |
|
|
|
681 |
jds |
59 |
static size_t FindMemorySize(CONST VOIDPTR ptr, int * CONST found) |
682 |
aw0a |
1 |
{ |
683 |
|
|
int pos; |
684 |
|
|
pos = SearchForMemory(ptr); |
685 |
jds |
59 |
if (( pos >= 0 ) && |
686 |
jds |
97 |
( pos < f_memory_length)) { |
687 |
aw0a |
1 |
*found = 1; |
688 |
jds |
97 |
if (f_mem_rec[pos].ptr==ptr) return f_mem_rec[pos].size; |
689 |
aw0a |
1 |
} |
690 |
|
|
*found = 0; |
691 |
|
|
return 0; |
692 |
|
|
} |
693 |
|
|
|
694 |
jds |
59 |
VOIDPTR ascreallocf(VOIDPTR ptr, size_t size, CONST char *file, int line) |
695 |
aw0a |
1 |
{ |
696 |
jds |
59 |
size_t old_size; |
697 |
aw0a |
1 |
int found; |
698 |
|
|
VOIDPTR result; |
699 |
|
|
OpenLogFile(); |
700 |
|
|
if (AllocatedMemory(ptr,0)){ |
701 |
|
|
old_size = FindMemorySize(ptr,&found); |
702 |
|
|
if (!found){ |
703 |
jds |
97 |
FPRINTF(ASCERR,"realloc'ing a piece of an allocated block.\n"); |
704 |
aw0a |
1 |
} |
705 |
|
|
result = realloc(ptr,size); |
706 |
|
|
} |
707 |
|
|
else{ |
708 |
|
|
old_size = 0; |
709 |
jds |
59 |
if (ptr == NULL) { |
710 |
aw0a |
1 |
result = malloc(size); |
711 |
|
|
} else { |
712 |
jds |
59 |
WriteError("ascreallocf called on a deallocated piece of memory.", |
713 |
|
|
file, line); |
714 |
aw0a |
1 |
result = realloc(ptr,size); |
715 |
|
|
} |
716 |
|
|
} |
717 |
jds |
59 |
if (NULL == result) |
718 |
|
|
size = 0; |
719 |
|
|
ReallocateMemory(ptr,old_size,result,size,file,line); |
720 |
|
|
if (size >= old_size) |
721 |
jds |
97 |
f_memory_allocated += (size-old_size); |
722 |
jds |
59 |
else |
723 |
jds |
97 |
f_memory_allocated -= (old_size-size); |
724 |
|
|
if (f_memory_allocated > f_peak_memory_usage) |
725 |
|
|
f_peak_memory_usage = f_memory_allocated; |
726 |
aw0a |
1 |
return result; |
727 |
|
|
} |
728 |
|
|
|
729 |
|
|
void ascfreef(VOIDPTR ptr, CONST char *file, int line) |
730 |
|
|
{ |
731 |
jds |
59 |
size_t size; |
732 |
aw0a |
1 |
int found; |
733 |
jds |
59 |
|
734 |
|
|
if (NULL == ptr) |
735 |
|
|
return; |
736 |
|
|
|
737 |
aw0a |
1 |
OpenLogFile(); |
738 |
jds |
59 |
if (0 != AllocatedMemory(ptr,0)) { |
739 |
aw0a |
1 |
size = FindMemorySize(ptr,&found); |
740 |
|
|
if (!found){ /* indicates a problem */ |
741 |
jds |
59 |
WriteError("Deallocating a piece of an allocated block.", file, line); |
742 |
aw0a |
1 |
} |
743 |
|
|
else |
744 |
jds |
59 |
memset((char *)ptr, 0, size); /* clear the memory */ |
745 |
aw0a |
1 |
} |
746 |
jds |
59 |
else { |
747 |
|
|
WriteError("ascfreef called on a deallocated piece of memory.", file, line); |
748 |
aw0a |
1 |
size = 0; |
749 |
|
|
} |
750 |
|
|
DeallocateMemory(ptr,size,file,line); |
751 |
jds |
97 |
f_memory_allocated -= size; |
752 |
aw0a |
1 |
free(ptr); |
753 |
|
|
} |
754 |
|
|
|
755 |
jds |
59 |
VOIDPTR ascbcopyf(CONST VOIDPTR src, VOIDPTR dest, size_t length, |
756 |
|
|
CONST char *file, int line) |
757 |
aw0a |
1 |
{ |
758 |
jds |
59 |
UNUSED_PARAMETER(file); |
759 |
|
|
UNUSED_PARAMETER(line); |
760 |
aw0a |
1 |
OpenLogFile(); |
761 |
jds |
59 |
return memcpy(dest, src, length); |
762 |
aw0a |
1 |
} |
763 |
|
|
|
764 |
jds |
59 |
VOIDPTR ascbzerof(VOIDPTR dest, size_t length, CONST char *file, int line) |
765 |
aw0a |
1 |
{ |
766 |
jds |
59 |
UNUSED_PARAMETER(file); |
767 |
|
|
UNUSED_PARAMETER(line); |
768 |
aw0a |
1 |
OpenLogFile(); |
769 |
jds |
59 |
return memset((char *)dest, 0, length); |
770 |
aw0a |
1 |
} |
771 |
|
|
|
772 |
jds |
59 |
int InMemoryBlockF(CONST VOIDPTR ptr1, CONST VOIDPTR ptr2) |
773 |
aw0a |
1 |
{ |
774 |
|
|
int pos; |
775 |
|
|
pos = SearchForMemory(ptr1); |
776 |
jds |
59 |
if (( pos >= 0 ) && |
777 |
jds |
97 |
( pos < f_memory_length ) && |
778 |
|
|
( f_mem_rec[pos].ptr == ptr1 )) |
779 |
jds |
59 |
return (( ptr2 >= ptr1 ) && |
780 |
jds |
97 |
( ptr2 < (CONST VOIDPTR)((CONST char *)ptr1 + f_mem_rec[pos].size))); |
781 |
aw0a |
1 |
else |
782 |
|
|
return 0; |
783 |
|
|
} |
784 |
johnpye |
938 |
|
785 |
|
|
#endif |