home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / gfx / 3d / irit / misc_lib / imalloc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-27  |  10.0 KB  |  270 lines

  1. /******************************************************************************
  2. * All mallocs from irit modules should be piped through this allocator.       *
  3. *                                          *
  4. *                     Written by Gershon Elber, April 1993 *
  5. ******************************************************************************/
  6.  
  7. #include <stdio.h>
  8. #include <string.h>
  9. #ifdef sgi
  10. #include <malloc.h>
  11. #endif /* sgi */
  12. #include "irit_sm.h"
  13. #include "imalloc.h"
  14.  
  15. #define OVERWRITE_STAMP_START 1234567890L    /* A long */
  16. #define OVERWRITE_STAMP_END   0xbd         /* A byte */
  17. #define OVERWRITE_STAMP_FREED -50964L        /* A long */
  18. #define FREE_TABLE_SIZE 100000
  19.  
  20. #if defined(AMIGA) && defined(__SASC)
  21. static VoidPtr __far *AllocPtrTable = NULL;
  22. #else
  23. static VoidPtr *AllocPtrTable = NULL;
  24. #endif
  25. static long
  26.     IritDebugSearchPtr = 0;
  27. static int
  28.     AllocNumPtrs = 0,
  29.     IritDebugMalloc = FALSE,
  30.     IritDebugMallocInit = FALSE;
  31.  
  32. static void AllocError(char *Msg, VoidPtr *p);
  33.  
  34. /*****************************************************************************
  35. * DESCRIPTION:                                                               *
  36. * Routine to print an allocation error to stderr happend when pointer p      *
  37. * was involved.                                              *
  38. *                                                                            *
  39. * PARAMETERS:                                                                *
  40. *   Msg:         A description of the error.                                 *
  41. *   p:           Pointer that is involved in the error.                      *
  42. *                                                                            *
  43. * RETURN VALUE:                                                              *
  44. *   void                                                                     *
  45. *****************************************************************************/
  46. static void AllocError(char *Msg, VoidPtr *p)
  47. {
  48.     char s[128];
  49.  
  50.     sprintf(s, "%s, Ptr = 0x%lx", Msg, (unsigned long) p);
  51.  
  52.     fprintf(stderr, "Memory allocation error, %s\n", s);
  53. }
  54.  
  55. /*****************************************************************************
  56. * DESCRIPTION:                                                               M
  57. * Tests for error in dynamically allocated memory, without affecting any     M
  58. * such allocation or allocated blocks.                            M
  59. *   This routine may be used only if "IRIT_MALLOC" environment variable      M
  60. * is set for debugging purposes and it obviously slows down running time.    M
  61. *   The following tests are being made on every block allocated,and messages M
  62. * are printed to stderr as needed:                         M
  63. * 1. Overwriting beyond the end of the allocated block.                 M
  64. * 2. Overwriting below the beginning of the allocated block.             M
  65. * 3. Freeing an unallocated pointer.                         M
  66. * 4. Freeing the same pointer twice.                         M
  67. * 5. If "IRIT_MALLOC_PTR" environment variable is set to an address, this    M
  68. *    address is being search for during allocation (IritMalloc) and          M
  69. *    announced when detected.                             M
  70. *                                                                            *
  71. * PARAMETERS:                                                                M
  72. *   PrintAlloc:   If TRUE, prints information all all allocated block, not   M
  73. *                 just block with errors.                     M
  74. *                                                                            *
  75. * RETURN VALUE:                                                              M
  76. *   void                                                                     M
  77. *                                                                            *
  78. * KEYWORDS:                                                                  M
  79. *   IritTestAllDynMemory, allocation                                         M
  80. *****************************************************************************/
  81. void IritTestAllDynMemory(int PrintAlloc)
  82. {
  83.     int i;
  84.  
  85.     if (AllocPtrTable == NULL) {
  86.     fprintf(stderr, "Allocation table was not initialized (call IritMalloc once)\n");
  87.     }
  88.  
  89.     for (i = 0; i < AllocNumPtrs; i++) {
  90.     if (AllocPtrTable[i] != NULL) {
  91.         unsigned long
  92.         size = *((unsigned long *) AllocPtrTable[i]);
  93.         VoidPtr
  94.         p2 = ((char *) AllocPtrTable[i]) + 8 + size;
  95.  
  96.         if (*((long *) ((char *) AllocPtrTable[i] + 4)) !=
  97.                         OVERWRITE_STAMP_START)
  98.         AllocError("Overwritten start of dynamically allocated memory",
  99.                AllocPtrTable[i]);
  100.         else if (*((unsigned char *) p2) != OVERWRITE_STAMP_END)
  101.         AllocError("Overwritten end of dynamically allocated memory",
  102.                AllocPtrTable[i]);
  103.  
  104.         if (PrintAlloc)
  105.         fprintf(stderr, "Allocated 0x%08lx\n",
  106.             (unsigned long) AllocPtrTable[i]);
  107.     }
  108.     }
  109. }
  110.  
  111. /*****************************************************************************
  112. * DESCRIPTION:                                                               M
  113. * Routine to allocate dynamic memory for all IRIT program/tool/libraries.    M
  114. *    All requests for dynamic memory should invoke this function.         M
  115. *    If the environment variable "IRIT_MALLOC" is set when an IRIT program   M
  116. * is executed, the consistency of the dynamic memory is tested on every      M
  117. * invokation of this routine. See IritTestAllDynMemory function for more.    M
  118. *                                                                            *
  119. * PARAMETERS:                                                                M
  120. *   size:     Size of block to allocate, in bytes.                           M
  121. *                                                                            *
  122. * RETURN VALUE:                                                              M
  123. *   VoidPtr:  A pointer to the allocated block. A function calling this      M
  124. *             may assume return value wil never be NULL, since no more       M
  125. *             memory cases are trapped locally.                     M
  126. *                                                                            *
  127. * KEYWORDS:                                                                  M
  128. *   IritMalloc, allocation                                                   M
  129. *****************************************************************************/
  130. VoidPtr IritMalloc(unsigned size)
  131. {
  132.     VoidPtr p;
  133.     unsigned int OldSize;
  134.  
  135.     if (!IritDebugMallocInit) {
  136.         IritDebugMalloc = getenv("IRIT_MALLOC") != NULL;
  137.         IritDebugSearchPtr = getenv("IRIT_MALLOC_PTR") != NULL ?
  138.                     atoi(getenv("IRIT_MALLOC_PTR")) : 0;
  139. #       ifdef sgi
  140.         mallopt(M_MXFAST, 256);
  141.         mallopt(M_BLKSZ, 65536);
  142. #       endif /* sgi */
  143.  
  144.     if (IritDebugMalloc)
  145.         AllocPtrTable = malloc(FREE_TABLE_SIZE * sizeof(VoidPtr));
  146.  
  147.     IritDebugMallocInit = TRUE;
  148.     }
  149.  
  150.     if (IritDebugMalloc) {
  151.     IritTestAllDynMemory(0);
  152.  
  153.     OldSize = size;
  154.     size += 16;
  155.     }
  156.  
  157.     if ((p = malloc(size)) != NULL) {
  158.     if (IritDebugMalloc) {
  159.         int i;
  160.         VoidPtr p2;
  161.  
  162.         if (p != NULL && ((long) p) == IritDebugSearchPtr) {
  163.         printf("Pointer 0x%08lx just allocated\n",
  164.                (unsigned long) p);
  165.         }
  166.  
  167.         /* Save allocated pointer so we can search for it when freed. */
  168.         for (i = 0; i < AllocNumPtrs; i++) {
  169.             if (AllocPtrTable[i] == NULL) {
  170.             AllocPtrTable[i] = p;
  171.             break;
  172.         }
  173.         }
  174.  
  175.         if (i >= AllocNumPtrs) {
  176.         if (i < FREE_TABLE_SIZE - 1)
  177.             AllocPtrTable[AllocNumPtrs++] = p;
  178.         else {
  179.             fprintf(stderr, "Allocation table too small.\n");
  180.             exit(1);
  181.         }
  182.         }
  183.  
  184.         *((long *) p) = OldSize;
  185.         *((long *) (((char *) p) + 4)) = OVERWRITE_STAMP_START;
  186.         p = ((char *) p) + 8;
  187.         p2 = ((char *) p) + OldSize;
  188.         *((char *) p2) = (char) OVERWRITE_STAMP_END;
  189.  
  190.         *((char *) p) = 0; /* In case the freed stamp is still there. */
  191.     }
  192.         
  193.     return p;
  194.     }
  195.  
  196.     IritFatalError("Not Enough dynamic memory");
  197.  
  198.     return NULL;                    /* Make warnings silent. */
  199. }
  200.  
  201. /*****************************************************************************
  202. * DESCRIPTION:                                                               M
  203. * Routine to free dynamic memory for all IRIT program/tool/libraries.        M
  204. *    All requests to free dynamic memory should invoke this function.        M
  205. *    If the environment variable "IRIT_MALLOC" is set when an IRIT program   M
  206. * is executed, the consistency of the dynamic memory is tested on every      M
  207. * invokation of this routine. See IritTestAllDynMemory function for more.    M
  208. *                                                                            *
  209. * PARAMETERS:                                                                M
  210. *   p:          Pointer to a block that needs to be freed.                   M
  211. *                                                                            *
  212. * RETURN VALUE:                                                              M
  213. *   void                                                                     M
  214. *                                                                            *
  215. * KEYWORDS:                                                                  M
  216. *   IritFree, allocation                                                     M
  217. *****************************************************************************/
  218. void IritFree(VoidPtr p)
  219. {
  220.     if (IritDebugMalloc) {
  221.     int i;
  222.  
  223.     if (*((long *) p) == OVERWRITE_STAMP_FREED)
  224.         AllocError("Trying to free a free object again", p);
  225.  
  226.     if (p == NULL)
  227.         AllocError("Free a NULL pointer", p);
  228.  
  229.     IritTestAllDynMemory(0);
  230.  
  231.     *((long *) p) = OVERWRITE_STAMP_FREED;
  232.     p = ((char *) p) - 8;
  233.  
  234.     /* Compare the freed pointer with the list of allocated ones. */
  235.     for (i = 0; i < AllocNumPtrs; i++) {
  236.         if (AllocPtrTable[i] == p) {
  237.         AllocPtrTable[i] = NULL;
  238.         break;
  239.         }
  240.     }
  241.  
  242.     if (i >= AllocNumPtrs)
  243.         AllocError("Free unallocated pointer", p);
  244.     }
  245.  
  246. #ifdef __DEBUG_TC_MALLOC__
  247.     switch (heapcheck()) {
  248.     case _HEAPCORRUPT:
  249.         AllocError("Heap is corrupted", p);
  250.         break;
  251.     case _BADNODE:
  252.         AllocError("Attempt to free a bogus pointer", p);
  253.         break;
  254.     case _FREEENTRY:
  255.         AllocError("Attempt to free an already freed pointer", p);
  256.         break;
  257.     case _HEAPOK:
  258.     case _HEAPEMPTY:
  259.     case _USEDENTRY:
  260.         break;
  261.     default:
  262.         AllocError("Allocation error", p);
  263.         break;
  264.  
  265.     }
  266. #endif /* __DEBUG_TC_MALLOC__ */
  267.  
  268.     free(p);
  269. }
  270.