Annotation of OpenXM_contrib/gnuplot/alloc.c, Revision 1.1
1.1 ! maekawa 1: #ifndef lint
! 2: static char *RCSid = "$Id: alloc.c,v 1.12 1998/03/22 22:31:16 drd Exp $";
! 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:
! 157: char *gp_alloc(size, usage)
! 158: unsigned long size;
! 159: char *usage;
! 160: {
! 161: struct frame_struct *p;
! 162: unsigned long total_size = size + RESERVED_SIZE + 1;
! 163:
! 164: TRACE_ALLOC(("gp_alloc %d for %s\n", (int) size, usage?usage:"<unknown>"));
! 165:
! 166: p=malloc(total_size);
! 167: if (!p) int_error("Out of memory", NO_CARET);
! 168:
! 169: bytes_allocated += size;
! 170:
! 171: mark(p,size,usage);
! 172:
! 173: return (char *)(p+1);
! 174: }
! 175:
! 176: generic *gp_realloc(old, size, usage)
! 177: generic *old;
! 178: unsigned long size;
! 179: char *usage;
! 180: {
! 181: if (!old) return gp_alloc(size, usage);
! 182: validate(old);
! 183: mark_free(old); /* if block gets moved, old block is marked free */
! 184: /* if not, we'll remark it later */
! 185:
! 186:
! 187: {
! 188: struct frame_struct *p = (struct frame_struct *)old - 1;
! 189: unsigned long total = size + RESERVED_SIZE + 1;
! 190:
! 191: p = realloc(p, total);
! 192:
! 193: if (!p) int_error("Out of memory", NO_CARET);
! 194:
! 195: TRACE_ALLOC(("gp_realloc %d for %s (was %d)\n",
! 196: (int)size, usage?usage:"<unknown>", p->requested_size));
! 197:
! 198: bytes_allocated += size - p->requested_size;
! 199:
! 200: mark(p,size,usage);
! 201:
! 202: return (generic *)(p+1);
! 203: }
! 204: }
! 205:
! 206: #undef free
! 207:
! 208: void checked_free(p)
! 209: void *p;
! 210: {
! 211: validate(p);
! 212: mark_free(p); /* trap attempts to free twice */
! 213: TRACE_ALLOC(("free %d for %s\n",
! 214: ((struct frame_struct *)p - 1)->requested_size,
! 215: ((struct frame_struct *)p - 1)->use));
! 216: bytes_allocated -= ((struct frame_struct *)p - 1) -> requested_size;
! 217: free( (struct frame_struct *) p - 1);
! 218: }
! 219:
! 220:
! 221: /* this leak checking stuff will be broken by first int_error or interrupt */
! 222:
! 223: void start_leak_check(char *file, int line)
! 224: {
! 225: if (leak_frame >= leak_stack+40)
! 226: {
! 227: fprintf(stderr, "too many nested memory-leak checks - %s:%d\n", file, line);
! 228: return;
! 229: }
! 230:
! 231: leak_frame->file = file;
! 232: leak_frame->line = line;
! 233: leak_frame->allocated = bytes_allocated;
! 234:
! 235: ++leak_frame;
! 236: }
! 237:
! 238: void end_leak_check(char *file, int line)
! 239: {
! 240: if (--leak_frame < leak_stack)
! 241: {
! 242: fprintf(stderr, "memory-leak stack underflow at %s:%d\n", file, line);
! 243: return;
! 244: }
! 245:
! 246: if (leak_frame->allocated != bytes_allocated)
! 247: {
! 248: fprintf(stderr, "net change of %+d heap bytes between %s:%d and %s:%d\n",
! 249: (int)(bytes_allocated - leak_frame->allocated),
! 250: leak_frame->file, leak_frame->line, file, line);
! 251: }
! 252: }
! 253:
! 254: #else /* CHECK_HEAP_USE */
! 255:
! 256: /* gp_alloc:
! 257: * allocate memory
! 258: * This is a protected version of malloc. It causes an int_error
! 259: * if there is not enough memory, but first it tries FreeHelp()
! 260: * to make some room, and tries again. If message is NULL, we
! 261: * allow NULL return. Otherwise, we handle the error, using the
! 262: * message to create the int_error string. Note cp/sp_extend uses realloc,
! 263: * so it depends on this using malloc().
! 264: */
! 265:
! 266: char *
! 267: gp_alloc(size, message)
! 268: unsigned long size; /* # of bytes */
! 269: char *message; /* description of what is being allocated */
! 270: {
! 271: char *p; /* the new allocation */
! 272: char errbuf[100]; /* error message string */
! 273:
! 274: #ifndef NO_GIH
! 275: p = GP_FARMALLOC(size);
! 276: if (p == (char *)NULL) {
! 277: FreeHelp(); /* out of memory, try to make some room */
! 278: #endif /* NO_GIH */
! 279: p = GP_FARMALLOC(size); /* try again */
! 280: if (p == (char *)NULL) {
! 281: /* really out of memory */
! 282: if (message != NULL) {
! 283: (void) sprintf(errbuf, "out of memory for %s", message);
! 284: int_error(errbuf, NO_CARET);
! 285: /* NOTREACHED */
! 286: }
! 287: /* else we return NULL */
! 288: }
! 289: #ifndef NO_GIH
! 290: }
! 291: #endif
! 292: return(p);
! 293: }
! 294:
! 295: /*
! 296: * note gp_realloc assumes that failed realloc calls leave the original mem block
! 297: * allocated. If this is not the case with any C compiler, a substitue
! 298: * realloc function has to be used.
! 299: */
! 300:
! 301: generic *
! 302: gp_realloc(p, size, message)
! 303: generic *p; /* old mem block */
! 304: unsigned long size; /* # of bytes */
! 305: char *message; /* description of what is being allocated */
! 306: {
! 307: char *res; /* the new allocation */
! 308: char errbuf[100]; /* error message string */
! 309:
! 310: /* realloc(NULL,x) is meant to do malloc(x), but doesn't always */
! 311: if (!p)
! 312: return gp_alloc(size,message);
! 313:
! 314: #ifndef NO_GIH
! 315: res = GP_FARREALLOC(p,size);
! 316: if (res == (char *)NULL) {
! 317: FreeHelp(); /* out of memory, try to make some room */
! 318: #endif /* NO_GIH */
! 319: res = GP_FARREALLOC(p,size); /* try again */
! 320: if (res == (char *)NULL) {
! 321: /* really out of memory */
! 322: if (message != NULL) {
! 323: (void) sprintf(errbuf, "out of memory for %s", message);
! 324: int_error(errbuf, NO_CARET);
! 325: /* NOTREACHED */
! 326: }
! 327: /* else we return NULL */
! 328: }
! 329: #ifndef NO_GIH
! 330: }
! 331: #endif
! 332: return(res);
! 333: }
! 334:
! 335: #endif /* CHECK_HEAP_USE */
! 336:
! 337: #ifdef FARALLOC
! 338: void gpfree(p)
! 339: generic *p;
! 340: {
! 341: #ifdef _Windows
! 342: HGLOBAL hGlobal = GlobalHandle(SELECTOROF(p));
! 343: GlobalUnlock(hGlobal);
! 344: GlobalFree(hGlobal);
! 345: #else
! 346: farfree(p);
! 347: #endif
! 348: }
! 349: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>