1: /*_ mem.c       */
  2: /* Memory management package    */
  3: /* Written by Walter Bright     */
  4: 
  5: #include        <stdio.h>
  6: #if MSDOS || __OS2__ || __NT__ || _WIN32
  7: #include        <io.h>
  8: #else
  9: #define _near
 10: #include        <sys/time.h>
 11: #include        <sys/resource.h>
 12: #include        <unistd.h>
 13: #endif
 14: #include        <stdarg.h>
 15: #include        <stddef.h>
 16: 
 17: #if __cplusplus
 18: #if __DMC__
 19: #include        <new.h>
 20: #else
 21: #include        <new>
 22: #endif
 23: #endif
 24: 
 25: #ifndef malloc
 26: #if __SC__ || __DMC__
 27: #include        <malloc.h>
 28: #else
 29: #include        <stdlib.h>
 30: #endif
 31: #endif
 32: 
 33: #ifndef MEM_H
 34: #include        "mem.h"
 35: #endif
 36: 
 37: #ifndef MEM_NOMEMCOUNT
 38: #define MEM_NOMEMCOUNT  0
 39: #endif
 40: 
 41: #if !MEM_NONE
 42: 
 43: #ifndef assert
 44: #include        <assert.h>
 45: #endif
 46: 
 47: #ifndef VAX11C
 48: #ifdef BSDUNIX
 49: #include <strings.h>
 50: #else
 51: #include <string.h>
 52: #endif
 53: #else
 54: extern char *strcpy(),*memcpy();
 55: extern int strlen();
 56: #endif  /* VAX11C */
 57: 
 58: int mem_inited = 0;             /* != 0 if initialized                  */
 59: 
 60: static int mem_behavior = MEM_ABORTMSG;
 61: static int (*fp)(void) = NULL;  /* out-of-memory handler                */
 62: static int mem_count;           /* # of allocs that haven't been free'd */
 63: static int mem_scount;          /* # of sallocs that haven't been free'd */
 64: 
 65: /* Determine where to send error messages       */
 66: #if _WINDLL
 67: void err_message(const char *,...);
 68: #define PRINT   err_message(
 69: #elif MSDOS
 70: #define PRINT   printf( /* stderr can't be redirected with MS-DOS       */
 71: #else
 72: #define ferr    stderr
 73: #define PRINT   fprintf(ferr,
 74: #endif
 75: 
 76: /*******************************/
 77: 
 78: void mem_setexception(enum MEM_E flag,...)
 79: {   va_list ap;
 80:     typedef int (*fp_t)(void);
 81: 
 82:     mem_behavior = flag;
 83:     va_start(ap,flag);
 84:     fp = (mem_behavior == MEM_CALLFP) ? va_arg(ap,fp_t) : 0;
 85:     va_end(ap);
 86: #if MEM_DEBUG
 87:     assert(0 <= flag && flag <= MEM_RETRY);
 88: #endif
 89: }
 90: 
 91: /*************************
 92:  * This is called when we're out of memory.
 93:  * Returns:
 94:  *      1:      try again to allocate the memory
 95:  *      0:      give up and return NULL
 96:  */
 97: 
 98: int mem_exception()
 99: {   int behavior;
100: 
101:     behavior = mem_behavior;
102:     while (1)
103:     {
104:         switch (behavior)
105:         {
106:             case MEM_ABORTMSG:
107: #if MSDOS || __OS2__ || __NT__ || _WIN32
108:                 /* Avoid linking in buffered I/O */
109:             {   static char msg[] = "Fatal error: out of memory\r\n";
110: 
111:                 write(1,msg,sizeof(msg) - 1);
warning C4996: 'write': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _write. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\io.h(318) : see declaration of 'write'
warning C6031: Return value ignored: 'write'
112: } 113: #else 114: PRINT "Fatal error: out of memory\n"); 115: #endif 116: /* FALL-THROUGH */ 117: case MEM_ABORT: 118: exit(EXIT_FAILURE); 119: /* NOTREACHED */ 120: case MEM_CALLFP: 121: assert(fp); 122: behavior = (*fp)(); 123: break; 124: case MEM_RETNULL: 125: return 0; 126: case MEM_RETRY: 127: return 1; 128: default: 129: assert(0); 130: } 131: } 132: } 133: 134: /****************************/ 135: 136: #if MEM_DEBUG 137: 138: #undef mem_strdup 139: 140: char *mem_strdup(const char *s) 141: { 142: return mem_strdup_debug(s,__FILE__,__LINE__); 143: } 144: 145: char *mem_strdup_debug(const char *s,const char *file,int line) 146: { 147: char *p; 148: 149: p = s 150: ? (char *) mem_malloc_debug((unsigned) strlen(s) + 1,file,line) 151: : NULL; 152: return p ? strcpy(p,s) : p; 153: } 154: #else 155: char *mem_strdup(const char *s) 156: { 157: char *p; 158: int len; 159: 160: if (s) 161: { len = strlen(s) + 1; 162: p = (char *) mem_malloc(len); 163: if (p) 164: return (char *)memcpy(p,s,len); 165: } 166: return NULL; 167: } 168: 169: #endif /* MEM_DEBUG */ 170: 171: /************* C++ Implementation ***************/ 172: 173: #if __cplusplus && !MEM_NONE 174: extern "C++" 175: { 176: 177: /* Cause initialization and termination functions to be called */ 178: #if 0 179: static struct cMemDebug 180: { 181: cMemDebug() { mem_init(); } 182: ~cMemDebug() { mem_term(); } 183: } dummy; 184: #endif 185: 186: int __mem_line; 187: char *__mem_file; 188: 189: /******************** 190: */ 191: 192: #if __GNUC__ 193: int (*_new_handler)(void); 194: #else 195: void (*_new_handler)(void); 196: #endif 197: 198: /***************************** 199: * Replacement for the standard C++ library operator new(). 200: */ 201: 202: #if !MEM_NONEW 203: 204: #if __GNUC__ 205: void * operator new(size_t size) 206: #else 207: #undef new 208: void * __cdecl operator new(size_t size) 209: #endif 210: { void *p; 211: 212: while (1) 213: { 214: if (size == 0) 215: size++; 216: #if MEM_DEBUG 217: assert(mem_inited); 218: p = mem_malloc_debug(size,__mem_file,__mem_line); 219: #else 220: p = mem_malloc((unsigned)size); 221: #endif 222: if (p != NULL || _new_handler == NULL) 223: break; 224: (*_new_handler)(); 225: } 226: return p; 227: } 228: 229: #if __GNUC__ 230: void * operator new[](size_t size) 231: #else 232: void * __cdecl operator new[](size_t size) 233: #endif 234: { void *p; 235: 236: while (1) 237: { 238: if (size == 0) 239: size++; 240: #if MEM_DEBUG 241: assert(mem_inited); 242: p = mem_malloc_debug(size,__mem_file,__mem_line); 243: #else 244: p = mem_malloc((unsigned)size); 245: #endif 246: if (p != NULL || _new_handler == NULL) 247: break; 248: (*_new_handler)(); 249: } 250: return p; 251: } 252: 253: /*********************** 254: * Replacement for the standard C++ library operator delete(). 255: */ 256: 257: #undef delete 258: void __cdecl operator delete(void *p) 259: { 260: #if MEM_DEBUG 261: assert(mem_inited); 262: mem_free_debug(p,__mem_file,__mem_line); 263: #else 264: mem_free(p); 265: #endif 266: } 267: 268: void __cdecl operator delete[](void *p) 269: { 270: #if MEM_DEBUG 271: assert(mem_inited); 272: mem_free_debug(p,__mem_file,__mem_line); 273: #else 274: mem_free(p); 275: #endif 276: } 277: #endif 278: } 279: #endif 280: 281: #if MEM_DEBUG 282: 283: static long mem_maxalloc; /* max # of bytes allocated */ 284: static long mem_numalloc; /* current # of bytes allocated */ 285: 286: #define BEFOREVAL 0x4F464542 /* value to detect underrun */ 287: #define AFTERVAL 0x45544641 /* value to detect overrun */ 288: 289: #if SUN || SUN386 290: static long afterval = AFTERVAL; /* so we can do &afterval */ 291: #endif 292: 293: /* The following should be selected to give maximum probability that */ 294: /* pointers loaded with these values will cause an obvious crash. On */ 295: /* Unix machines, a large value will cause a segment fault. */ 296: /* MALLOCVAL is the value to set malloc'd data to. */ 297: 298: #if MSDOS || __OS2__ || __NT__ || _WIN32 299: #define BADVAL 0xFF 300: #define MALLOCVAL 0xEE 301: #else 302: #define BADVAL 0x7A 303: #define MALLOCVAL 0xEE 304: #endif 305: 306: /* Disable mapping macros */ 307: #undef mem_malloc 308: #undef mem_calloc 309: #undef mem_realloc 310: #undef mem_free 311: 312: /* Create a list of all alloc'ed pointers, retaining info about where */ 313: /* each alloc came from. This is a real memory and speed hog, but who */ 314: /* cares when you've got obscure pointer bugs. */ 315: 316: static struct mem_debug 317: { 318: struct mem_debug *Mnext; /* next in list */ 319: struct mem_debug *Mprev; /* previous value in list */ 320: const char *Mfile; /* filename of where allocated */ 321: int Mline; /* line number of where allocated */ 322: unsigned Mnbytes; /* size of the allocation */ 323: unsigned long Mbeforeval; /* detect underrun of data */ 324: char data[1]; /* the data actually allocated */ 325: } mem_alloclist = 326: { 327: (struct mem_debug *) NULL, 328: (struct mem_debug *) NULL, 329: NULL, 330: 11111, 331: 0, 332: BEFOREVAL, 333: #if !(linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4) 334: AFTERVAL 335: #endif 336: }; 337: 338: /* Determine allocation size of a mem_debug */ 339: #define mem_debug_size(n) (sizeof(struct mem_debug) - 1 + (n) + sizeof(AFTERVAL)) 340: 341: /* Convert from a void *to a mem_debug struct. */ 342: #define mem_ptrtodl(p) ((struct mem_debug *) ((char *)p - offsetof(struct mem_debug,data[0]))) 343: 344: /* Convert from a mem_debug struct to a mem_ptr. */ 345: #define mem_dltoptr(dl) ((void *) &((dl)->data[0])) 346: 347: /***************************** 348: * Set new value of file,line 349: */ 350: 351: void mem_setnewfileline( void *ptr, const char *fil, int lin) 352: { 353: struct mem_debug *dl; 354: 355: dl = mem_ptrtodl(ptr); 356: dl->Mfile = fil; 357: dl->Mline = lin; 358: } 359: 360: /**************************** 361: * Print out struct mem_debug. 362: */ 363: 364: static void _near mem_printdl(struct mem_debug *dl) 365: { 366: PRINT "alloc'd from file '%s' line %d nbytes %d ptr %p\n", 367: dl->Mfile,dl->Mline,dl->Mnbytes,(long)mem_dltoptr(dl)); 368: } 369: 370: /**************************** 371: * Print out file and line number. 372: */ 373: 374: static void _near mem_fillin(const char *fil, int lin) 375: { 376: PRINT "File '%s' line %d\n",fil,lin); 377: #ifdef ferr 378: fflush(ferr); 379: #endif 380: } 381: 382: /**************************** 383: * If MEM_DEBUG is not on for some modules, these routines will get 384: * called. 385: */ 386: 387: void *mem_calloc(unsigned u) 388: { 389: return mem_calloc_debug(u,__FILE__,__LINE__); 390: } 391: 392: void *mem_malloc(unsigned u) 393: { 394: return mem_malloc_debug(u,__FILE__,__LINE__); 395: } 396: 397: void *mem_realloc(void *p, unsigned u) 398: { 399: return mem_realloc_debug(p,u,__FILE__,__LINE__); 400: } 401: 402: void mem_free(void *p) 403: { 404: mem_free_debug(p,__FILE__,__LINE__); 405: } 406: 407: 408: /**************************/ 409: 410: void mem_freefp(void *p) 411: { 412: mem_free(p); 413: } 414: 415: /*********************** 416: * Debug versions of mem_calloc(), mem_free() and mem_realloc(). 417: */ 418: 419: void *mem_malloc_debug(unsigned n, const char *fil, int lin) 420: { void *p; 421: 422: p = mem_calloc_debug(n,fil,lin); 423: if (p) 424: memset(p,MALLOCVAL,n); 425: return p; 426: } 427: 428: void *mem_calloc_debug(unsigned n, const char *fil, int lin) 429: { 430: struct mem_debug *dl; 431: 432: do 433: dl = (struct mem_debug *) calloc(mem_debug_size(n),1); 434: while (dl == NULL && mem_exception()); 435: if (dl == NULL) 436: return NULL; 437: dl->Mfile = fil; 438: dl->Mline = lin; 439: dl->Mnbytes = n; 440: dl->Mbeforeval = BEFOREVAL; 441: #if SUN || SUN386 /* bus error if we store a long at an odd address */ 442: memcpy(&(dl->data[n]),&afterval,sizeof(AFTERVAL)); 443: #else 444: *(long *) &(dl->data[n]) = AFTERVAL; 445: #endif 446: 447: /* Add dl to start of allocation list */ 448: dl->Mnext = mem_alloclist.Mnext; 449: dl->Mprev = &mem_alloclist; 450: mem_alloclist.Mnext = dl; 451: if (dl->Mnext != NULL) 452: dl->Mnext->Mprev = dl; 453: 454: mem_count++; 455: mem_numalloc += n; 456: if (mem_numalloc > mem_maxalloc) 457: mem_maxalloc = mem_numalloc; 458: return mem_dltoptr(dl); 459: } 460: 461: void mem_free_debug(void *ptr, const char *fil, int lin) 462: { 463: struct mem_debug *dl; 464: 465: if (ptr == NULL) 466: return; 467: if (mem_count <= 0) 468: { PRINT "More frees than allocs at "); 469: goto err; 470: } 471: dl = mem_ptrtodl(ptr); 472: if (dl->Mbeforeval != BEFOREVAL) 473: { 474: PRINT "Pointer x%lx underrun\n",(long)ptr); 475: PRINT "'%s'(%d)\n",fil,lin); 476: goto err2; 477: } 478: #if SUN || SUN386 /* Bus error if we read a long from an odd address */ 479: if (memcmp(&dl->data[dl->Mnbytes],&afterval,sizeof(AFTERVAL)) != 0) 480: #else 481: if (*(long *) &dl->data[dl->Mnbytes] != AFTERVAL) 482: #endif 483: { 484: PRINT "Pointer x%lx overrun\n",(long)ptr); 485: goto err2; 486: } 487: mem_numalloc -= dl->Mnbytes; 488: if (mem_numalloc < 0) 489: { PRINT "error: mem_numalloc = %ld, dl->Mnbytes = %d\n", 490: mem_numalloc,dl->Mnbytes); 491: goto err2; 492: } 493: 494: /* Remove dl from linked list */ 495: if (dl->Mprev) 496: dl->Mprev->Mnext = dl->Mnext; 497: if (dl->Mnext) 498: dl->Mnext->Mprev = dl->Mprev; 499: 500: /* Stomp on the freed storage to help detect references */ 501: /* after the storage was freed. */ 502: memset((void *) dl,BADVAL,sizeof(*dl) + dl->Mnbytes); 503: mem_count--; 504: 505: free((void *) dl); 506: return; 507: 508: err2: 509: mem_printdl(dl); 510: err: 511: PRINT "free'd from "); 512: mem_fillin(fil,lin); 513: assert(0); 514: /* NOTREACHED */ 515: } 516: 517: /******************* 518: * Debug version of mem_realloc(). 519: */ 520: 521: void *mem_realloc_debug(void *oldp, unsigned n, const char *fil, int lin) 522: { void *p; 523: struct mem_debug *dl; 524: 525: if (n == 0) 526: { mem_free_debug(oldp,fil,lin); 527: p = NULL; 528: } 529: else if (oldp == NULL) 530: p = mem_malloc_debug(n,fil,lin); 531: else 532: { 533: p = mem_malloc_debug(n,fil,lin); 534: if (p != NULL) 535: { 536: dl = mem_ptrtodl(oldp); 537: if (dl->Mnbytes < n) 538: n = dl->Mnbytes; 539: memcpy(p,oldp,n); 540: mem_free_debug(oldp,fil,lin); 541: } 542: } 543: return p; 544: } 545: 546: /***************************/ 547: 548: static void mem_checkdl(struct mem_debug *dl) 549: { void *p; 550: #if (__SC__ || __DMC__) && !_WIN32 551: unsigned u; 552: 553: /* Take advantage of fact that SC's allocator stores the size of the 554: * alloc in the unsigned immediately preceding the allocation. 555: */ 556: u = ((unsigned *)dl)[-1] - sizeof(unsigned); 557: assert((u & (sizeof(unsigned) - 1)) == 0 && u >= mem_debug_size(dl->Mnbytes)); 558: #endif 559: p = mem_dltoptr(dl); 560: if (dl->Mbeforeval != BEFOREVAL) 561: { 562: PRINT "Pointer x%lx underrun\n",(long)p); 563: goto err2; 564: } 565: #if SUN || SUN386 /* Bus error if we read a long from an odd address */ 566: if (memcmp(&dl->data[dl->Mnbytes],&afterval,sizeof(AFTERVAL)) != 0) 567: #else 568: if (*(long *) &dl->data[dl->Mnbytes] != AFTERVAL) 569: #endif 570: { 571: PRINT "Pointer x%lx overrun\n",(long)p); 572: goto err2; 573: } 574: return; 575: 576: err2: 577: mem_printdl(dl); 578: assert(0); 579: } 580: 581: /***************************/ 582: 583: void mem_check() 584: { register struct mem_debug *dl; 585: 586: #if (__SC__ || _MSC_VER) && !defined(malloc) 587: int i; 588: 589: i = _heapset(0xF4); 590: assert(i == _HEAPOK); 591: #endif 592: for (dl = mem_alloclist.Mnext; dl != NULL; dl = dl->Mnext) 593: mem_checkdl(dl); 594: } 595: 596: /***************************/ 597: 598: void mem_checkptr(void *p) 599: { register struct mem_debug *dl; 600: 601: for (dl = mem_alloclist.Mnext; dl != NULL; dl = dl->Mnext) 602: { 603: if (p >= (void *) &(dl->data[0]) && 604: p < (void *)((char *)dl + sizeof(struct mem_debug)-1 + dl->Mnbytes)) 605: goto L1; 606: } 607: assert(0); 608: 609: L1: 610: mem_checkdl(dl); 611: } 612: 613: #else 614: 615: /***************************/ 616: 617: void *mem_malloc(unsigned numbytes) 618: { void *p; 619: 620: if (numbytes == 0) 621: return NULL; 622: while (1) 623: { 624: p = malloc(numbytes); 625: if (p == NULL) 626: { if (mem_exception()) 627: continue; 628: } 629: #if !MEM_NOMEMCOUNT 630: else 631: mem_count++; 632: #endif 633: break; 634: } 635: /*printf("malloc(%d) = x%lx, mem_count = %d\n",numbytes,p,mem_count);*/ 636: return p; 637: } 638: 639: /***************************/ 640: 641: void *mem_calloc(unsigned numbytes) 642: { void *p; 643: 644: if (numbytes == 0) 645: return NULL; 646: while (1) 647: { 648: p = calloc(numbytes,1); 649: if (p == NULL) 650: { if (mem_exception()) 651: continue; 652: } 653: #if !MEM_NOMEMCOUNT 654: else 655: mem_count++; 656: #endif 657: break; 658: } 659: /*printf("calloc(%d) = x%lx, mem_count = %d\n",numbytes,p,mem_count);*/ 660: return p; 661: } 662: 663: /***************************/ 664: 665: void *mem_realloc(void *oldmem_ptr,unsigned newnumbytes) 666: { void *p; 667: 668: if (oldmem_ptr == NULL) 669: p = mem_malloc(newnumbytes); 670: else if (newnumbytes == 0) 671: { mem_free(oldmem_ptr); 672: p = NULL; 673: } 674: else 675: { 676: do 677: p = realloc(oldmem_ptr,newnumbytes);
warning C6001: Using uninitialized memory 'oldmem_ptr': Lines: 666, 668, 670, 677
678: while (p == NULL && mem_exception()); 679: } 680: /*printf("realloc(x%lx,%d) = x%lx, mem_count = %d\n",oldmem_ptr,newnumbytes,p,mem_count);*/ 681: return p; 682: } 683: 684: /***************************/ 685: 686: void mem_free(void *ptr) 687: { 688: /*printf("free(x%lx) mem_count=%d\n",ptr,mem_count);*/ 689: if (ptr != NULL) 690: { 691: #if !MEM_NOMEMCOUNT 692: assert(mem_count != 0); 693: mem_count--; 694: #endif 695: free(ptr); 696: } 697: } 698: 699: /***************************/ 700: /* This is our low-rent fast storage allocator */ 701: 702: static char *heap; 703: static size_t heapleft; 704: 705: /***************************/ 706: 707: #if 0 && __SC__ && __INTSIZE == 4 && __I86__ && !_DEBUG_TRACE && _WIN32 && (SCC || SCPP || JAVA) 708: 709: __declspec(naked) void *mem_fmalloc(unsigned numbytes) 710: { 711: __asm 712: { 713: mov EDX,4[ESP] 714: mov EAX,heap 715: add EDX,3 716: mov ECX,heapleft 717: and EDX,~3 718: je L5A 719: cmp EDX,ECX 720: ja L2D 721: sub ECX,EDX 722: add EDX,EAX 723: mov heapleft,ECX 724: mov heap,EDX 725: ret 4 726: 727: L2D: push EBX 728: mov EBX,EDX 729: // add EDX,03FFFh 730: // and EDX,~03FFFh 731: add EDX,03C00h 732: mov heapleft,EDX 733: L3D: push heapleft 734: call mem_malloc 735: test EAX,EAX 736: mov heap,EAX 737: jne L18 738: call mem_exception 739: test EAX,EAX 740: jne L3D 741: pop EBX 742: L5A: xor EAX,EAX 743: ret 4 744: 745: L18: add heap,EBX 746: sub heapleft,EBX 747: pop EBX 748: ret 4 749: } 750: } 751: 752: #else 753: 754: void *mem_fmalloc(unsigned numbytes) 755: { void *p; 756: 757: //printf("fmalloc(%d)\n",numbytes); 758: if (sizeof(size_t) == 2) 759: numbytes = (numbytes + 1) & ~1; /* word align */ 760: else 761: numbytes = (numbytes + 3) & ~3; /* dword align */ 762: 763: /* This ugly flow-of-control is so that the most common case 764: drops straight through. 765: */ 766: 767: if (!numbytes) 768: return NULL; 769: 770: if (numbytes <= heapleft) 771: { 772: L2: 773: p = (void *)heap; 774: heap += numbytes; 775: heapleft -= numbytes; 776: return p; 777: } 778: 779: #if 1 780: heapleft = numbytes + 0x3C00; 781: if (heapleft >= 16372) 782: heapleft = numbytes; 783: #elif _WIN32 784: heapleft = (numbytes + 0x3FFF) & ~0x3FFF; /* round to next boundary */ 785: #else 786: heapleft = 0x3F00; 787: assert(numbytes <= heapleft); 788: #endif 789: L1: 790: heap = (char *)malloc(heapleft); 791: if (!heap) 792: { if (mem_exception()) 793: goto L1; 794: return NULL; 795: } 796: goto L2; 797: } 798: 799: #endif 800: 801: /***************************/ 802: 803: void *mem_fcalloc(unsigned numbytes) 804: { void *p; 805: 806: p = mem_fmalloc(numbytes); 807: return p ? memset(p,0,numbytes) : p; 808: } 809: 810: /***************************/ 811: 812: char *mem_fstrdup(const char *s) 813: { 814: char *p; 815: int len; 816: 817: if (s) 818: { len = strlen(s) + 1; 819: p = (char *) mem_fmalloc(len); 820: if (p) 821: return (char *)memcpy(p,s,len); 822: } 823: return NULL; 824: } 825: 826: #endif 827: 828: /***************************/ 829: 830: void mem_init() 831: { 832: if (mem_inited == 0) 833: { mem_count = 0; 834: mem_scount = 0; 835: fp = NULL; 836: mem_behavior = MEM_ABORTMSG; 837: #if MEM_DEBUG 838: mem_numalloc = 0; 839: mem_maxalloc = 0; 840: mem_alloclist.Mnext = NULL; 841: #if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4 842: *(long *) &(mem_alloclist.data[0]) = AFTERVAL; 843: #endif 844: #endif 845: #if (__ZTC__ || __SC__ || __DMC__) && !defined(malloc) 846: free(malloc(1)); /* initialize storage allocator */ 847: #endif 848: #if MEM_DEBUG && (__SC__ || _MSC_VER) && !defined(malloc) 849: { int i; 850: 851: i = _heapset(0xF4); 852: assert(i == _HEAPOK); 853: } 854: #endif 855: } 856: mem_inited++; 857: } 858: 859: /***************************/ 860: 861: void mem_term() 862: { 863: if (mem_inited) 864: { 865: #if MEM_DEBUG 866: struct mem_debug *dl; 867: 868: for (dl = mem_alloclist.Mnext; dl; dl = dl->Mnext) 869: { PRINT "Unfreed pointer: "); 870: mem_printdl(dl); 871: } 872: #if 0 873: PRINT "Max amount ever allocated == %ld bytes\n", 874: mem_maxalloc); 875: #endif 876: #if (__SC__ || _MSC_VER) && !defined(malloc) 877: { int i; 878: 879: i = _heapset(0xF4); 880: assert(i == _HEAPOK); 881: } 882: #endif 883: #else 884: if (mem_count) 885: PRINT "%d unfreed items\n",mem_count); 886: if (mem_scount) 887: PRINT "%d unfreed s items\n",mem_scount); 888: #endif /* MEM_DEBUG */ 889: assert(mem_count == 0 && mem_scount == 0); 890: } 891: mem_inited = 0; 892: } 893: 894: #endif /* !MEM_NONE */ 895: