Annotation of OpenXM_contrib/gnuplot/alloc.c, Revision 1.1.1.3
1.1 maekawa 1: #ifndef lint
1.1.1.3 ! ohara 2: static char *RCSid = "$Id: alloc.c,v 1.1.1.2.2.1 2001/06/25 16:06:34 broeker Exp $";
1.1 maekawa 3: #endif
4:
5: /* GNUPLOT - alloc.c */
6:
7: /*[
8: * Copyright 1986 - 1993, 1998 Thomas Williams, Colin Kelley
9: *
10: * Permission to use, copy, and distribute this software and its
11: * documentation for any purpose with or without fee is hereby granted,
12: * provided that the above copyright notice appear in all copies and
13: * that both that copyright notice and this permission notice appear
14: * in supporting documentation.
15: *
16: * Permission to modify the software is granted, but not the right to
17: * distribute the complete modified source code. Modifications are to
18: * be distributed as patches to the released version. Permission to
19: * distribute binaries produced by compiling modified sources is granted,
20: * provided you
21: * 1. distribute the corresponding source modifications from the
22: * released version in the form of a patch file along with the binaries,
23: * 2. add special version identification to distinguish your version
24: * in addition to the base release version number,
25: * 3. provide your name and address as the primary contact for the
26: * support of your modified version, and
27: * 4. retain our contact information in regard to use of the base
28: * software.
29: * Permission to distribute the released version of the source code along
30: * with corresponding source modifications in the form of a patch file is
31: * granted with same provisions 2 through 4 for binary distributions.
32: *
33: * This software is provided "as is" without express or implied warranty
34: * to the extent permitted by applicable law.
35: ]*/
36:
37: /*
38: * AUTHORS
39: *
40: * Alexander Lehmann (collected functions from misc.c and binary.c)
41: *
42: */
43:
44: #include "plot.h" /* includes "alloc.h" */
45:
46: #if defined(MSDOS) && defined(__TURBOC__) && !defined(DOSX286)
47: #include <alloc.h> /* for farmalloc, farrealloc */
48: #endif
49:
50: #if defined(_Windows) && !defined(WIN32)
51: #include <windows.h>
52: #include <windowsx.h>
53: #define farmalloc(s) GlobalAllocPtr(GHND,s)
54: #define farrealloc(p,s) GlobalReAllocPtr(p,s,GHND)
55: #endif
56:
57: #ifndef NO_GIH
58: #include "help.h"
59: #endif
60:
61: #ifndef GP_FARMALLOC
62: # ifdef FARALLOC
63: # define GP_FARMALLOC(size) farmalloc ((size))
64: # define GP_FARREALLOC(p,size) farrealloc ((p), (size))
65: # else
66: # define GP_FARMALLOC(size) malloc ((size_t)(size))
67: # define GP_FARREALLOC(p,size) realloc ((p), (size_t)(size))
68: # endif
69: #endif
70:
71: /* uncomment if you want to trace all allocs */
72: #define TRACE_ALLOC(x) /*printf x*/
73:
74:
75: #ifdef CHECK_HEAP_USE
76:
77: /* This is in no way supported, and in particular it breaks the
78: * online help. But it is useful to leave it in in case any
79: * heap-corruption bugs turn up. Wont work with FARALLOC
80: */
81:
82: struct frame_struct {
83: char *use;
84: int requested_size;
85: int pad; /* preserve 8-byte alignment */
86: int checksum;
87: };
88:
89: struct leak_struct {
90: char *file;
91: int line;
92: int allocated;
93: };
94:
95: static struct leak_struct leak_stack[40]; /* up to 40 nested leak checks */
96: static struct leak_struct *leak_frame = leak_stack;
97:
98: static long bytes_allocated = 0;
99:
100: #define RESERVED_SIZE sizeof(struct frame_struct)
101: #define CHECKSUM_INT 0xcaac5e1f
102: #define CHECKSUM_FREE 0xf3eed222
103: #define CHECKSUM_CHAR 0xc5
104:
105: static void mark(p, size, usage)
106: struct frame_struct *p;
107: unsigned long size;
108: char *usage;
109: {
110: p->use = usage;
111: p->requested_size = size;
112: p->checksum = (CHECKSUM_INT ^ (int)(p->use) ^ size);
113: ((unsigned char *)(p+1))[size] = CHECKSUM_CHAR;
114: }
115:
116: #define mark_free(p) ( ((struct frame_struct *)p)[-1].checksum = CHECKSUM_FREE)
117:
118: static void validate(x)
119: void *x;
120: {
121: struct frame_struct *p = (struct frame_struct *)x - 1;
122: if (p->checksum != (CHECKSUM_INT ^ (int)(p->use) ^ p->requested_size))
123: {
124: fprintf(stderr, "Heap corruption at start of block for %s\n", p->use);
125: if (p->checksum == CHECKSUM_FREE)
126: fprintf(stderr, "Looks like it has already been freed ?\n");
127: abort();
128: }
129:
130: if ( ((unsigned char *)(p+1))[p->requested_size] != CHECKSUM_CHAR)
131: {
132: fprintf(stderr, "Heap corruption at end of block for %-60s\n", p->use);
133: int_error("Argh !", NO_CARET);
134: }
135: }
136:
137: /* used to confirm that a pointer is inside an allocated region via
138: * macro CHECK_POINTER. Nowhere near as good as using a bounds-checking
139: * compiler (such as gcc-with-bounds-checking), but when we do
140: * come across problems, we can add these guards to the code until
141: * we find the problem, and then leave the guards in (as CHECK_POINTER
142: * macros which expand to nothing, until we need to re-enable them)
143: */
144:
145: void check_pointer_in_block(void *block, void *p, int size, char *file, int line)
146: {
147: struct frame_struct *f = (struct frame_struct *)block - 1;
148: validate(block);
149: if (p < block || p >= (block + f->requested_size))
150: {
151: fprintf(stderr, "argh - pointer %p outside block %p->%p for %s at %s:%d\n",
152: p, block, (char *)block + f->requested_size, f->use, file, line);
153: int_error("argh - pointer misuse !", NO_CARET);
154: }
155: }
156:
1.1.1.3 ! ohara 157: generic *
! 158: gp_alloc(size, usage)
! 159: unsigned long size;
! 160: char *usage;
1.1 maekawa 161: {
162: struct frame_struct *p;
163: unsigned long total_size = size + RESERVED_SIZE + 1;
164:
165: TRACE_ALLOC(("gp_alloc %d for %s\n", (int) size, usage?usage:"<unknown>"));
166:
167: p=malloc(total_size);
168: if (!p) int_error("Out of memory", NO_CARET);
169:
170: bytes_allocated += size;
171:
172: mark(p,size,usage);
173:
174: return (char *)(p+1);
175: }
176:
177: generic *gp_realloc(old, size, usage)
178: generic *old;
179: unsigned long size;
180: char *usage;
181: {
182: if (!old) return gp_alloc(size, usage);
183: validate(old);
184: mark_free(old); /* if block gets moved, old block is marked free */
185: /* if not, we'll remark it later */
186:
187:
188: {
189: struct frame_struct *p = (struct frame_struct *)old - 1;
190: unsigned long total = size + RESERVED_SIZE + 1;
191:
192: p = realloc(p, total);
193:
194: if (!p) int_error("Out of memory", NO_CARET);
195:
196: TRACE_ALLOC(("gp_realloc %d for %s (was %d)\n",
197: (int)size, usage?usage:"<unknown>", p->requested_size));
198:
199: bytes_allocated += size - p->requested_size;
200:
201: mark(p,size,usage);
202:
203: return (generic *)(p+1);
204: }
205: }
206:
207: #undef free
208:
209: void checked_free(p)
210: void *p;
211: {
212: validate(p);
213: mark_free(p); /* trap attempts to free twice */
214: TRACE_ALLOC(("free %d for %s\n",
215: ((struct frame_struct *)p - 1)->requested_size,
216: ((struct frame_struct *)p - 1)->use));
217: bytes_allocated -= ((struct frame_struct *)p - 1) -> requested_size;
218: free( (struct frame_struct *) p - 1);
219: }
220:
221:
222: /* this leak checking stuff will be broken by first int_error or interrupt */
223:
224: void start_leak_check(char *file, int line)
225: {
226: if (leak_frame >= leak_stack+40)
227: {
228: fprintf(stderr, "too many nested memory-leak checks - %s:%d\n", file, line);
229: return;
230: }
231:
232: leak_frame->file = file;
233: leak_frame->line = line;
234: leak_frame->allocated = bytes_allocated;
235:
236: ++leak_frame;
237: }
238:
239: void end_leak_check(char *file, int line)
240: {
241: if (--leak_frame < leak_stack)
242: {
243: fprintf(stderr, "memory-leak stack underflow at %s:%d\n", file, line);
244: return;
245: }
246:
247: if (leak_frame->allocated != bytes_allocated)
248: {
249: fprintf(stderr, "net change of %+d heap bytes between %s:%d and %s:%d\n",
250: (int)(bytes_allocated - leak_frame->allocated),
251: leak_frame->file, leak_frame->line, file, line);
252: }
253: }
254:
255: #else /* CHECK_HEAP_USE */
256:
257: /* gp_alloc:
258: * allocate memory
259: * This is a protected version of malloc. It causes an int_error
260: * if there is not enough memory, but first it tries FreeHelp()
261: * to make some room, and tries again. If message is NULL, we
262: * allow NULL return. Otherwise, we handle the error, using the
263: * message to create the int_error string. Note cp/sp_extend uses realloc,
264: * so it depends on this using malloc().
265: */
266:
1.1.1.3 ! ohara 267: generic *
1.1 maekawa 268: gp_alloc(size, message)
269: unsigned long size; /* # of bytes */
270: char *message; /* description of what is being allocated */
271: {
272: char *p; /* the new allocation */
273: char errbuf[100]; /* error message string */
274:
275: #ifndef NO_GIH
276: p = GP_FARMALLOC(size);
277: if (p == (char *)NULL) {
278: FreeHelp(); /* out of memory, try to make some room */
279: #endif /* NO_GIH */
280: p = GP_FARMALLOC(size); /* try again */
281: if (p == (char *)NULL) {
282: /* really out of memory */
283: if (message != NULL) {
284: (void) sprintf(errbuf, "out of memory for %s", message);
285: int_error(errbuf, NO_CARET);
286: /* NOTREACHED */
287: }
288: /* else we return NULL */
289: }
290: #ifndef NO_GIH
291: }
292: #endif
293: return(p);
294: }
295:
296: /*
297: * note gp_realloc assumes that failed realloc calls leave the original mem block
298: * allocated. If this is not the case with any C compiler, a substitue
299: * realloc function has to be used.
300: */
301:
302: generic *
303: gp_realloc(p, size, message)
304: generic *p; /* old mem block */
305: unsigned long size; /* # of bytes */
306: char *message; /* description of what is being allocated */
307: {
308: char *res; /* the new allocation */
309: char errbuf[100]; /* error message string */
310:
311: /* realloc(NULL,x) is meant to do malloc(x), but doesn't always */
312: if (!p)
313: return gp_alloc(size,message);
314:
315: #ifndef NO_GIH
316: res = GP_FARREALLOC(p,size);
317: if (res == (char *)NULL) {
318: FreeHelp(); /* out of memory, try to make some room */
319: #endif /* NO_GIH */
320: res = GP_FARREALLOC(p,size); /* try again */
321: if (res == (char *)NULL) {
322: /* really out of memory */
323: if (message != NULL) {
324: (void) sprintf(errbuf, "out of memory for %s", message);
325: int_error(errbuf, NO_CARET);
326: /* NOTREACHED */
327: }
328: /* else we return NULL */
329: }
330: #ifndef NO_GIH
331: }
332: #endif
333: return(res);
334: }
335:
336: #endif /* CHECK_HEAP_USE */
337:
338: #ifdef FARALLOC
339: void gpfree(p)
340: generic *p;
341: {
342: #ifdef _Windows
343: HGLOBAL hGlobal = GlobalHandle(SELECTOROF(p));
344: GlobalUnlock(hGlobal);
345: GlobalFree(hGlobal);
346: #else
347: farfree(p);
348: #endif
349: }
350: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>