2 static char *RCSid() { return RCSid("$Id: alloc.c,v 1.12 2006/03/17 16:09:03 broeker Exp $"); }
5 /* GNUPLOT - alloc.c */
8 * Copyright 1986 - 1993, 1998, 2004 Thomas Williams, Colin Kelley
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.
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,
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
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.
33 * This software is provided "as is" without express or implied warranty
34 * to the extent permitted by applicable law.
40 * Alexander Lehmann (collected functions from misc.c and binary.c)
51 #if defined(MSDOS) && defined(__TURBOC__) && !defined(DOSX286)
52 # include <alloc.h> /* for farmalloc, farrealloc */
55 #if defined(_Windows) && !defined(WIN32)
57 # include <windowsx.h>
58 # define farmalloc(s) GlobalAllocPtr(GHND,s)
59 # define farrealloc(p,s) GlobalReAllocPtr(p,s,GHND)
66 # define GP_FARMALLOC(size) farmalloc ((size))
67 # define GP_FARREALLOC(p,size) farrealloc ((p), (size))
69 # define GP_FARMALLOC(size) malloc ((size_t)(size))
70 # define GP_FARREALLOC(p,size) realloc ((p), (size_t)(size))
74 /* uncomment if you want to trace all allocs */
75 #define TRACE_ALLOC(x) /*printf x */
80 /* This is in no way supported, and in particular it breaks the
81 * online help. But it is useful to leave it in in case any
82 * heap-corruption bugs turn up. Wont work with FARALLOC
88 int pad; /* preserve 8-byte alignment */
98 static struct leak_struct leak_stack[40]; /* up to 40 nested leak checks */
99 static struct leak_struct *leak_frame = leak_stack;
101 static long bytes_allocated = 0;
103 #define RESERVED_SIZE sizeof(struct frame_struct)
104 #define CHECKSUM_INT 0xcaac5e1f
105 #define CHECKSUM_FREE 0xf3eed222
106 #define CHECKSUM_CHAR 0xc5
109 mark(struct frame_struct *p, unsigned long size, char *usage)
112 p->requested_size = size;
113 p->checksum = (CHECKSUM_INT ^ (int) (p->use) ^ size);
114 ((unsigned char *) (p + 1))[size] = CHECKSUM_CHAR;
117 #define mark_free(p) ( ((struct frame_struct *)p)[-1].checksum = CHECKSUM_FREE)
122 struct frame_struct *p = (struct frame_struct *) x - 1;
123 if (p->checksum != (CHECKSUM_INT ^ (int) (p->use) ^ p->requested_size)) {
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");
129 if (((unsigned char *) (p + 1))[p->requested_size] != CHECKSUM_CHAR) {
130 fprintf(stderr, "Heap corruption at end of block for %-60s\n", p->use);
131 int_error(NO_CARET, "Argh !");
135 /* used to confirm that a pointer is inside an allocated region via
136 * macro CHECK_POINTER. Nowhere near as good as using a bounds-checking
137 * compiler (such as gcc-with-bounds-checking), but when we do
138 * come across problems, we can add these guards to the code until
139 * we find the problem, and then leave the guards in (as CHECK_POINTER
140 * macros which expand to nothing, until we need to re-enable them)
144 check_pointer_in_block(generic *block, generic *p, int size, char *file, int line)
146 struct frame_struct *f = (struct frame_struct *) block - 1;
148 if (p < block || p >= (block + f->requested_size)) {
149 fprintf(stderr, "argh - pointer %p outside block %p->%p for %s at %s:%d\n",
150 p, block, (char *) block + f->requested_size, f->use, file, line);
151 int_error(NO_CARET, "argh - pointer misuse !");
156 gp_alloc(size_t size, const char *usage)
158 struct frame_struct *p;
159 size_t total_size = size + RESERVED_SIZE + 1;
161 TRACE_ALLOC(("gp_alloc %d for %s\n", (int) size,
162 usage ? usage : "<unknown>"));
164 p = malloc(total_size);
166 int_error(NO_CARET, "Out of memory");
168 bytes_allocated += size;
170 mark(p, size, usage);
172 /* Cast possibly needed for K&R compilers */
173 return (generic *) (p + 1);
177 gp_realloc(generic *old, size_t size, const char *usage)
180 return gp_alloc(size, usage);
182 /* if block gets moved, old block is marked free. If not, we'll
187 struct frame_struct *p = (struct frame_struct *) old - 1;
188 size_t total = size + RESERVED_SIZE + 1;
190 p = realloc(p, total);
193 int_error(NO_CARET, "Out of memory");
195 TRACE_ALLOC(("gp_realloc %d for %s (was %d)\n", (int) size,
196 usage ? usage : "<unknown>", p->requested_size));
198 bytes_allocated += size - p->requested_size;
200 mark(p, size, usage);
202 return (generic *) (p + 1);
209 checked_free(generic *p)
211 struct frame_struct *frame;
214 mark_free(p); /* trap attempts to free twice */
215 frame = (struct frame_struct *) p - 1;
216 TRACE_ALLOC(("free %d for %s\n",
217 frame->requested_size,
218 (frame->use ? frame->use : "(NULL)")));
219 bytes_allocated -= frame->requested_size;
224 /* this leak checking stuff will be broken by first int_error or interrupt */
227 start_leak_check(char *file, int line)
229 if (leak_frame >= leak_stack + 40) {
230 fprintf(stderr, "too many nested memory-leak checks - %s:%d\n",
234 leak_frame->file = file;
235 leak_frame->line = line;
236 leak_frame->allocated = bytes_allocated;
242 end_leak_check(char *file, int line)
244 if (--leak_frame < leak_stack) {
245 fprintf(stderr, "memory-leak stack underflow at %s:%d\n", file, line);
248 if (leak_frame->allocated != bytes_allocated) {
250 "net change of %+d heap bytes between %s:%d and %s:%d\n",
251 (int) (bytes_allocated - leak_frame->allocated),
252 leak_frame->file, leak_frame->line, file, line);
256 #else /* CHECK_HEAP_USE */
260 * This is a protected version of malloc. It causes an int_error
261 * if there is not enough memory, but first it tries FreeHelp()
262 * to make some room, and tries again. If message is NULL, we
263 * allow NULL return. Otherwise, we handle the error, using the
264 * message to create the int_error string. Note cp/sp_extend uses realloc,
265 * so it depends on this using malloc().
269 gp_alloc(size_t size, const char *message)
271 char *p; /* the new allocation */
274 p = GP_FARMALLOC(size);
275 if (p == (char *) NULL) {
276 FreeHelp(); /* out of memory, try to make some room */
278 p = GP_FARMALLOC(size); /* try again */
280 /* really out of memory */
281 if (message != NULL) {
282 int_error(NO_CARET, "out of memory for %s", message);
285 /* else we return NULL */
294 * note gp_realloc assumes that failed realloc calls leave the original mem
295 * block allocated. If this is not the case with any C compiler, a substitue
296 * realloc function has to be used.
300 gp_realloc(generic *p, size_t size, const char *message)
302 char *res; /* the new allocation */
304 /* realloc(NULL,x) is meant to do malloc(x), but doesn't always */
306 return gp_alloc(size, message);
309 res = GP_FARREALLOC(p, size);
310 if (res == (char *) NULL) {
311 FreeHelp(); /* out of memory, try to make some room */
313 res = GP_FARREALLOC(p, size); /* try again */
314 if (res == (char *) NULL) {
315 /* really out of memory */
316 if (message != NULL) {
317 int_error(NO_CARET, "out of memory for %s", message);
320 /* else we return NULL */
328 #endif /* CHECK_HEAP_USE */
335 HGLOBAL hGlobal = GlobalHandle(SELECTOROF(p));
336 GlobalUnlock(hGlobal);