home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / mem / mem.c < prev    next >
C/C++ Source or Header  |  1998-06-08  |  13KB  |  525 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: f:/miner/source/mem/rcs/mem.c $
  15.  * $Revision: 1.18 $
  16.  * $Author: matt $
  17.  * $Date: 1995/01/24 20:49:18 $
  18.  * 
  19.  * Files for debugging memory allocator
  20.  * 
  21.  * $Log: mem.c $
  22.  * Revision 1.18  1995/01/24  20:49:18  matt
  23.  * Made some stuff return when get errors
  24.  * 
  25.  * Revision 1.17  1994/11/29  15:40:38  matt
  26.  * Added extra newline after message
  27.  * 
  28.  * Revision 1.16  1994/11/15  18:27:56  john
  29.  * Took away show mem info by default.
  30.  * 
  31.  * Revision 1.15  1994/11/10  10:00:37  john
  32.  * Made it show_mem_info by default.
  33.  * 
  34.  * Revision 1.14  1994/11/10  09:53:06  john
  35.  * Put in more efficient, but less debugging info version.
  36.  * 
  37.  * Revision 1.13  1994/10/27  00:56:45  john
  38.  * Reduced number of blocks; made show mem usage by default.
  39.  * 
  40.  * Revision 1.12  1994/10/06  19:15:17  john
  41.  * Upped the number of blocks.
  42.  * 
  43.  * 
  44.  * Revision 1.11  1994/07/27  20:04:22  john
  45.  * Neatend printed output.
  46.  * 
  47.  * Revision 1.10  1994/07/20  10:22:17  yuan
  48.  * Added overwrite error
  49.  * 
  50.  * Revision 1.9  1994/03/23  12:58:43  john
  51.  * Made message global.
  52.  * 
  53.  * Revision 1.8  1994/03/15  11:12:59  john
  54.  * Made calloc fill block with zeros like it's
  55.  * supposed to.
  56.  * 
  57.  * Revision 1.7  1994/02/18  12:43:21  john
  58.  * Only print mem debugging info if show_mem_info
  59.  * is true. Need to set in debugger, btw.
  60.  * 
  61.  * Revision 1.6  1994/02/17  17:01:34  john
  62.  * Took out MEM_LEAKAGE warning!
  63.  * 
  64.  * Revision 1.5  1994/01/24  16:04:47  john
  65.  * Added mem_print_all function to dump all
  66.  * allocated memory to inferno.mem file.
  67.  * 
  68.  * 
  69.  * Revision 1.4  1994/01/18  11:01:41  john
  70.  * *** empty log message ***
  71.  * 
  72.  * Revision 1.3  1993/12/10  12:20:50  john
  73.  * Speed up by replacing mem_find_unused_id with a table lookup.
  74.  * 
  75.  * Revision 1.2  1993/12/08  12:38:22  mike
  76.  * Change 10000 to MAX_INDEX
  77.  * Use LargestIndex in place of MAX_INDEX as appropriate.
  78.  * 
  79.  * Revision 1.1  1993/11/02  17:45:28  john
  80.  * Initial revision
  81.  * 
  82.  * 
  83.  */
  84.  
  85.  
  86. #pragma off (unreferenced)
  87. static char rcsid[] = "$Id: mem.c 1.18 1995/01/24 20:49:18 matt Exp $";
  88. #pragma on (unreferenced)
  89.  
  90.  
  91. // Warning( "MEM: Too many malloc's!" );
  92. // Warning( "MEM: Malloc returnd an already alloced block!" );
  93. // Warning( "MEM: Malloc Failed!" );
  94. // Warning( "MEM: Freeing the NULL pointer!" );
  95. // Warning( "MEM: Freeing a non-malloced pointer!" );
  96. // Warning( "MEM: %d/%d check bytes were overwritten at the end of %8x", ec, CHECKSIZE, buffer  );
  97. // Warning( "MEM: %d blocks were left allocated!", numleft );
  98.  
  99. #include <stdio.h>
  100. #include <stdlib.h>
  101. #include <stdarg.h>
  102. #include <string.h>
  103. #include <dos.h>
  104. #include <malloc.h>
  105.  
  106. #include "mono.h"
  107. #include "error.h"
  108.  
  109. //#define FULL_MEM_CHECKING
  110.  
  111. #ifdef FULL_MEM_CHECKING 
  112.  
  113. #define CHECKSIZE 16
  114. #define CHECKBYTE 0xFC
  115.  
  116. #define MAX_INDEX 10000
  117.  
  118. static unsigned int MallocBase[MAX_INDEX];
  119. static unsigned int MallocSize[MAX_INDEX];
  120. static unsigned int MallocRealSize[MAX_INDEX];
  121. static unsigned char Present[MAX_INDEX];
  122. static char * Filename[MAX_INDEX];
  123. static char * Varname[MAX_INDEX];
  124. static int Line[MAX_INDEX];
  125. static int BytesMalloced = 0;
  126.  
  127. static unsigned int SmallestAddress = 0xFFFFFFF;
  128. static unsigned int LargestAddress = 0x0;
  129.  
  130. int show_mem_info = 1;
  131.  
  132. static int free_list[MAX_INDEX];
  133.  
  134. static int num_blocks = 0;
  135.  
  136. static int Initialized = 0;
  137.  
  138. static int LargestIndex = 0;
  139.  
  140. int out_of_memory = 0;
  141.  
  142. void mem_display_blocks();
  143.  
  144. void mem_init()
  145. {
  146.     int i;
  147.     
  148.     Initialized = 1;
  149.  
  150.     for (i=0; i<MAX_INDEX; i++ )
  151.     {
  152.         free_list[i] = i;
  153.         MallocBase[i] = 0;
  154.         MallocSize[i] = 0;
  155.         MallocRealSize[i] = 0;
  156.         Present[i] = 0;
  157.         Filename[i] = NULL;
  158.         Varname[i] = NULL;
  159.         Line[i] = 0;
  160.     }
  161.  
  162.     SmallestAddress = 0xFFFFFFF;
  163.     LargestAddress = 0x0;
  164.  
  165.     num_blocks = 0;
  166.     LargestIndex = 0;
  167.  
  168.     atexit(mem_display_blocks);
  169.  
  170. }
  171.  
  172. void PrintInfo( int id )
  173. {
  174.     fprintf( stderr, "\tBlock '%s' created in %s, line %d.\n", Varname[id], Filename[id], Line[id] );
  175. }
  176.  
  177.  
  178. void * mem_malloc( unsigned int size, char * var, char * filename, int line, int fill_zero )
  179. {
  180.     unsigned int base;
  181.     int i, j, id;
  182.     void *ptr;
  183.     char * pc;
  184.     int * data;
  185.  
  186.     if (Initialized==0)
  187.         mem_init();
  188.  
  189.     if ( num_blocks >= MAX_INDEX )    {
  190.         fprintf( stderr,"\nMEM_OUT_OF_SLOTS: Not enough space in mem.c to hold all the mallocs.\n" );        
  191.         fprintf( stderr, "\tBlock '%s' created in %s, line %d.\n", var, filename, line );
  192.         Error( "MEM_OUT_OF_SLOTS" );
  193.     }
  194.  
  195.     id = free_list[ num_blocks++ ];
  196.  
  197.     if (id > LargestIndex ) LargestIndex = id;
  198.  
  199.     if (id==-1)
  200.     {
  201.         fprintf( stderr,"\nMEM_OUT_OF_SLOTS: Not enough space in mem.c to hold all the mallocs.\n" );        
  202.         fprintf( stderr, "\tBlock '%s' created in %s, line %d.\n", Varname[id], Filename[id], Line[id] );
  203.         Error( "MEM_OUT_OF_SLOTS" );
  204.     }
  205.  
  206.     ptr = malloc( size+CHECKSIZE );
  207.  
  208.     /*
  209.     for (j=0; j<=LargestIndex; j++ )
  210.     {
  211.         if (Present[j] && MallocBase[j] == (unsigned int)ptr )
  212.         {
  213.             fprintf( stderr,"\nMEM_SPACE_USED: Malloc returned a block that is already marked as preset.\n" );
  214.             fprintf( stderr, "\tBlock '%s' created in %s, line %d.\n", Varname[id], Filename[id], Line[id] );
  215.             Warning( "MEM_SPACE_USED" );
  216.             Int3();
  217.             }
  218.     }
  219.     */
  220.  
  221.     if (ptr==NULL)
  222.     {
  223.         out_of_memory = 1;
  224.         fprintf( stderr, "\nMEM_OUT_OF_MEMORY: Malloc returned NULL\n" );
  225.         fprintf( stderr, "\tBlock '%s' created in %s, line %d.\n", Varname[id], Filename[id], Line[id] );
  226.         Error( "MEM_OUT_OF_MEMORY" );
  227.         Int3();
  228.     }
  229.  
  230.     base = (unsigned int)ptr;
  231.     if ( base < SmallestAddress ) SmallestAddress = base;
  232.     if ( (base+size) > LargestAddress ) LargestAddress = base+size;
  233.  
  234.     MallocBase[id] = (unsigned int)ptr;
  235.     data = (int *)((int)MallocBase[id]-4);
  236.     MallocRealSize[id] = *data;
  237.     MallocSize[id] = size;
  238.     Varname[id] = var;
  239.     Filename[id] = filename;
  240.     Line[id] = line;
  241.     Present[id]    = 1;
  242.  
  243.     pc = (char *)ptr;
  244.  
  245.     BytesMalloced += size;
  246.  
  247.     for (i=0; i<CHECKSIZE; i++ )
  248.         pc[size+i] = CHECKBYTE;
  249.  
  250.     if (fill_zero)
  251.         memset( ptr, 0, size );
  252.  
  253.     return ptr;
  254.  
  255. }
  256.  
  257. int mem_find_id( void * buffer )
  258. {
  259.     int i;
  260.  
  261.     for (i=0; i<=LargestIndex; i++ )
  262.         if (Present[i]==1)
  263.             if (MallocBase[i] == (unsigned int)buffer )
  264.                 return i;
  265.  
  266.     // Didn't find id.
  267.     return -1;
  268. }
  269.  
  270. int mem_check_integrity( int block_number )
  271. {
  272.     int * data;
  273.     int i, ErrorCount;
  274.     char * CheckData;
  275.  
  276.     CheckData = (char *)(MallocBase[block_number] + MallocSize[block_number]);
  277.  
  278.     data = (int *)((int)MallocBase[block_number]-4);
  279.  
  280.     if ( *data != MallocRealSize[block_number] )    {
  281.         fprintf( stderr, "\nMEM_BAD_LENGTH: The length field of an allocated block was overwritten.\n" );
  282.         PrintInfo( block_number );
  283.         //Int3();
  284.         *data = MallocRealSize[block_number];
  285.     }
  286.  
  287.     ErrorCount = 0;
  288.             
  289.     for (i=0; i<CHECKSIZE; i++ )
  290.         if (CheckData[i] != CHECKBYTE ) {
  291.             ErrorCount++;
  292.             fprintf( stderr, "OA: %x ", &CheckData[i] );
  293.         }
  294.  
  295.     if (ErrorCount &&  (!out_of_memory))    {
  296.         fprintf( stderr, "\nMEM_OVERWRITE: Memory after the end of allocated block overwritten.\n" );
  297.         PrintInfo( block_number );
  298.         fprintf( stderr, "\t%d/%d check bytes were overwritten.\n", ErrorCount, CHECKSIZE );
  299.     }
  300.  
  301.     return ErrorCount;
  302.  
  303. }
  304.  
  305. void mem_free( void * buffer )
  306. {
  307.     int id;
  308.  
  309.     if (Initialized==0)
  310.         mem_init();
  311.  
  312.     if (buffer==NULL  &&  (!out_of_memory))
  313.     {
  314.         fprintf( stderr, "\nMEM_FREE_NULL: An attempt was made to free the null pointer.\n" );
  315.         Warning( "MEM: Freeing the NULL pointer!" );
  316.         Int3();
  317.         return;
  318.     }
  319.  
  320.     id = mem_find_id( buffer );
  321.  
  322.     if (id==-1 &&  (!out_of_memory))
  323.     {
  324.         fprintf( stderr, "\nMEM_FREE_NOMALLOC: An attempt was made to free a ptr that wasn't\nallocated with mem.h included.\n" );
  325.         Warning( "MEM: Freeing a non-malloced pointer!" );
  326.         Int3();
  327.         return;
  328.     }
  329.     
  330.     mem_check_integrity( id );
  331.     
  332.     BytesMalloced -= MallocSize[id];
  333.  
  334.     free( buffer );
  335.     
  336.     
  337.     Present[id] = 0;
  338.     MallocBase[id] = 0;
  339.     MallocSize[id] = 0;
  340.  
  341.     free_list[ --num_blocks ] = id;
  342. }
  343.  
  344. void mem_display_blocks()
  345. {
  346.     int i, numleft;
  347.  
  348.     if (Initialized==0) return;
  349.     
  350.     numleft = 0;
  351.     for (i=0; i<=LargestIndex; i++ )
  352.     {
  353.         if (Present[i]==1 &&  (!out_of_memory))
  354.         {
  355.             numleft++;
  356.             if (show_mem_info)    {
  357.                 fprintf( stderr, "\nMEM_LEAKAGE: Memory block has not been freed.\n" );
  358.                 PrintInfo( i );
  359.             }
  360.             mem_free( (void *)MallocBase[i] );
  361.         }
  362.     }
  363.  
  364.     if (numleft &&  (!out_of_memory))
  365.     {
  366.         Warning( "MEM: %d blocks were left allocated!", numleft );
  367.     }
  368.  
  369.     if (show_mem_info)    {
  370.         fprintf( stderr, "\n\nMEMORY USAGE:\n" );
  371.         fprintf( stderr, "  %u Kbytes dynamic data\n", (LargestAddress-SmallestAddress+512)/1024 );
  372.         fprintf( stderr, "  %u Kbytes code/static data.\n", (SmallestAddress-(4*1024*1024)+512)/1024 );
  373.         fprintf( stderr, "  ---------------------------\n" );
  374.         fprintf( stderr, "  %u Kbytes required.\n\n",     (LargestAddress-(4*1024*1024)+512)/1024 );
  375.     }
  376. }
  377.  
  378. void mem_validate_heap()
  379. {
  380.     int i;
  381.     
  382.     for (i=0; i<LargestIndex; i++  )
  383.         if (Present[i]==1 )
  384.             mem_check_integrity( i );
  385. }
  386.  
  387. void mem_print_all()
  388. {
  389.     FILE * ef;
  390.     int i, size = 0;
  391.  
  392.     ef = fopen( "DESCENT.MEM", "wt" );
  393.     
  394.     for (i=0; i<LargestIndex; i++  )
  395.         if (Present[i]==1 )    {
  396.             size += MallocSize[i];
  397.             //fprintf( ef, "Var:%s\t File:%s\t Line:%d\t Size:%d Base:%x\n", Varname[i], Filename[i], Line[i], MallocSize[i], MallocBase[i] );
  398.             fprintf( ef, "%12d bytes in %s declared in %s, line %d\n", MallocSize[i], Varname[i], Filename[i], Line[i]  );
  399.         }
  400.     fprintf( ef, "%d bytes (%d Kbytes) allocated.\n", size, size/1024 ); 
  401.     fclose(ef);
  402. }
  403.  
  404. #else
  405.  
  406. static int Initialized = 0;
  407. static unsigned int SmallestAddress = 0xFFFFFFF;
  408. static unsigned int LargestAddress = 0x0;
  409. static unsigned int BytesMalloced = 0;
  410.  
  411. void mem_display_blocks();
  412.  
  413. #define CHECKSIZE 16
  414. #define CHECKBYTE 0xFC
  415.  
  416. int show_mem_info = 0;
  417.  
  418. void mem_init()
  419. {
  420.     Initialized = 1;
  421.  
  422.     SmallestAddress = 0xFFFFFFF;
  423.     LargestAddress = 0x0;
  424.  
  425.     atexit(mem_display_blocks);
  426. }
  427.  
  428. void * mem_malloc( unsigned int size, char * var, char * filename, int line, int fill_zero )
  429. {
  430.     unsigned int base;
  431.     void *ptr;
  432.     int * psize;
  433.  
  434.     if (Initialized==0)
  435.         mem_init();
  436.  
  437.     if (size==0)    {
  438.         fprintf( stderr, "\nMEM_MALLOC_ZERO: Attempting to malloc 0 bytes.\n" );
  439.         fprintf( stderr, "\tVar %s, file %s, line %d.\n", var, filename, line );
  440.         Error( "MEM_MALLOC_ZERO" );
  441.         Int3();
  442.     }
  443.  
  444.     ptr = malloc( size + CHECKSIZE );
  445.  
  446.     if (ptr==NULL)    {
  447.         fprintf( stderr, "\nMEM_OUT_OF_MEMORY: Malloc returned NULL\n" );
  448.         fprintf( stderr, "\tVar %s, file %s, line %d.\n", var, filename, line );
  449.         Error( "MEM_OUT_OF_MEMORY" );
  450.         Int3();
  451.     }
  452.  
  453.     base = (unsigned int)ptr;
  454.     if ( base < SmallestAddress ) SmallestAddress = base;
  455.     if ( (base+size) > LargestAddress ) LargestAddress = base+size;
  456.  
  457.  
  458.     psize = (int *)ptr;
  459.     psize--;
  460.     BytesMalloced += *psize;
  461.  
  462.     if (fill_zero)
  463.         memset( ptr, 0, size );
  464.  
  465.     return ptr;
  466. }
  467.  
  468. void mem_free( void * buffer )
  469. {
  470.     int ErrorCount;
  471.     int * psize = (int *)buffer;
  472.     psize--;
  473.  
  474.     if (Initialized==0)
  475.         mem_init();
  476.  
  477.     if (buffer==NULL)    {
  478.         fprintf( stderr, "\nMEM_FREE_NULL: An attempt was made to free the null pointer.\n" );
  479.         Warning( "MEM: Freeing the NULL pointer!" );
  480.         Int3();
  481.         return;
  482.     }
  483.  
  484.     ErrorCount = 0;
  485.  
  486.     if (ErrorCount)    {
  487.         fprintf( stderr, "\nMEM_OVERWRITE: Memory after the end of allocated block overwritten.\n" );
  488.         fprintf( stderr, "\tBlock at 0x%x, size %d\n", buffer, *psize );
  489.         fprintf( stderr, "\t%d/%d check bytes were overwritten.\n", ErrorCount, CHECKSIZE );
  490.     }
  491.  
  492.     BytesMalloced -= *psize;
  493.  
  494.     free( buffer );
  495. }
  496.  
  497. void mem_display_blocks()
  498. {
  499.     if (Initialized==0) return;
  500.  
  501.     if (BytesMalloced != 0 )    {
  502.         fprintf( stderr, "\nMEM_LEAKAGE: %d bytes of memory have not been freed.\n", BytesMalloced );
  503.     }
  504.  
  505.     if (show_mem_info)    {
  506.         fprintf( stderr, "\n\nMEMORY USAGE:\n" );
  507.         fprintf( stderr, "  %u Kbytes dynamic data\n", (LargestAddress-SmallestAddress+512)/1024 );
  508.         fprintf( stderr, "  %u Kbytes code/static data.\n", (SmallestAddress-(4*1024*1024)+512)/1024 );
  509.         fprintf( stderr, "  ---------------------------\n" );
  510.         fprintf( stderr, "  %u Kbytes required.\n",     (LargestAddress-(4*1024*1024)+512)/1024 );
  511.     }
  512. }
  513.  
  514. void mem_validate_heap()
  515. {
  516. }
  517.  
  518. void mem_print_all()
  519. {
  520. }
  521.  
  522. #endif
  523.  
  524.  
  525.