home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * All mallocs from irit modules should be piped through this allocator. *
- * *
- * Written by Gershon Elber, April 1993 *
- ******************************************************************************/
-
- #include <stdio.h>
- #include <string.h>
- #ifdef sgi
- #include <malloc.h>
- #endif /* sgi */
- #include "irit_sm.h"
- #include "imalloc.h"
-
- #define OVERWRITE_STAMP_START 1234567890L /* A long */
- #define OVERWRITE_STAMP_END 0xbd /* A byte */
- #define OVERWRITE_STAMP_FREED -50964L /* A long */
- #define FREE_TABLE_SIZE 100000
-
- #if defined(AMIGA) && defined(__SASC)
- static VoidPtr __far *AllocPtrTable = NULL;
- #else
- static VoidPtr *AllocPtrTable = NULL;
- #endif
- static long
- IritDebugSearchPtr = 0;
- static int
- AllocNumPtrs = 0,
- IritDebugMalloc = FALSE,
- IritDebugMallocInit = FALSE;
-
- static void AllocError(char *Msg, VoidPtr *p);
-
- /*****************************************************************************
- * DESCRIPTION: *
- * Routine to print an allocation error to stderr happend when pointer p *
- * was involved. *
- * *
- * PARAMETERS: *
- * Msg: A description of the error. *
- * p: Pointer that is involved in the error. *
- * *
- * RETURN VALUE: *
- * void *
- *****************************************************************************/
- static void AllocError(char *Msg, VoidPtr *p)
- {
- char s[128];
-
- sprintf(s, "%s, Ptr = 0x%lx", Msg, (unsigned long) p);
-
- fprintf(stderr, "Memory allocation error, %s\n", s);
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Tests for error in dynamically allocated memory, without affecting any M
- * such allocation or allocated blocks. M
- * This routine may be used only if "IRIT_MALLOC" environment variable M
- * is set for debugging purposes and it obviously slows down running time. M
- * The following tests are being made on every block allocated,and messages M
- * are printed to stderr as needed: M
- * 1. Overwriting beyond the end of the allocated block. M
- * 2. Overwriting below the beginning of the allocated block. M
- * 3. Freeing an unallocated pointer. M
- * 4. Freeing the same pointer twice. M
- * 5. If "IRIT_MALLOC_PTR" environment variable is set to an address, this M
- * address is being search for during allocation (IritMalloc) and M
- * announced when detected. M
- * *
- * PARAMETERS: M
- * PrintAlloc: If TRUE, prints information all all allocated block, not M
- * just block with errors. M
- * *
- * RETURN VALUE: M
- * void M
- * *
- * KEYWORDS: M
- * IritTestAllDynMemory, allocation M
- *****************************************************************************/
- void IritTestAllDynMemory(int PrintAlloc)
- {
- int i;
-
- if (AllocPtrTable == NULL) {
- fprintf(stderr, "Allocation table was not initialized (call IritMalloc once)\n");
- }
-
- for (i = 0; i < AllocNumPtrs; i++) {
- if (AllocPtrTable[i] != NULL) {
- unsigned long
- size = *((unsigned long *) AllocPtrTable[i]);
- VoidPtr
- p2 = ((char *) AllocPtrTable[i]) + 8 + size;
-
- if (*((long *) ((char *) AllocPtrTable[i] + 4)) !=
- OVERWRITE_STAMP_START)
- AllocError("Overwritten start of dynamically allocated memory",
- AllocPtrTable[i]);
- else if (*((unsigned char *) p2) != OVERWRITE_STAMP_END)
- AllocError("Overwritten end of dynamically allocated memory",
- AllocPtrTable[i]);
-
- if (PrintAlloc)
- fprintf(stderr, "Allocated 0x%08lx\n",
- (unsigned long) AllocPtrTable[i]);
- }
- }
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Routine to allocate dynamic memory for all IRIT program/tool/libraries. M
- * All requests for dynamic memory should invoke this function. M
- * If the environment variable "IRIT_MALLOC" is set when an IRIT program M
- * is executed, the consistency of the dynamic memory is tested on every M
- * invokation of this routine. See IritTestAllDynMemory function for more. M
- * *
- * PARAMETERS: M
- * size: Size of block to allocate, in bytes. M
- * *
- * RETURN VALUE: M
- * VoidPtr: A pointer to the allocated block. A function calling this M
- * may assume return value wil never be NULL, since no more M
- * memory cases are trapped locally. M
- * *
- * KEYWORDS: M
- * IritMalloc, allocation M
- *****************************************************************************/
- VoidPtr IritMalloc(unsigned size)
- {
- VoidPtr p;
- unsigned int OldSize;
-
- if (!IritDebugMallocInit) {
- IritDebugMalloc = getenv("IRIT_MALLOC") != NULL;
- IritDebugSearchPtr = getenv("IRIT_MALLOC_PTR") != NULL ?
- atoi(getenv("IRIT_MALLOC_PTR")) : 0;
- # ifdef sgi
- mallopt(M_MXFAST, 256);
- mallopt(M_BLKSZ, 65536);
- # endif /* sgi */
-
- if (IritDebugMalloc)
- AllocPtrTable = malloc(FREE_TABLE_SIZE * sizeof(VoidPtr));
-
- IritDebugMallocInit = TRUE;
- }
-
- if (IritDebugMalloc) {
- IritTestAllDynMemory(0);
-
- OldSize = size;
- size += 16;
- }
-
- if ((p = malloc(size)) != NULL) {
- if (IritDebugMalloc) {
- int i;
- VoidPtr p2;
-
- if (p != NULL && ((long) p) == IritDebugSearchPtr) {
- printf("Pointer 0x%08lx just allocated\n",
- (unsigned long) p);
- }
-
- /* Save allocated pointer so we can search for it when freed. */
- for (i = 0; i < AllocNumPtrs; i++) {
- if (AllocPtrTable[i] == NULL) {
- AllocPtrTable[i] = p;
- break;
- }
- }
-
- if (i >= AllocNumPtrs) {
- if (i < FREE_TABLE_SIZE - 1)
- AllocPtrTable[AllocNumPtrs++] = p;
- else {
- fprintf(stderr, "Allocation table too small.\n");
- exit(1);
- }
- }
-
- *((long *) p) = OldSize;
- *((long *) (((char *) p) + 4)) = OVERWRITE_STAMP_START;
- p = ((char *) p) + 8;
- p2 = ((char *) p) + OldSize;
- *((char *) p2) = (char) OVERWRITE_STAMP_END;
-
- *((char *) p) = 0; /* In case the freed stamp is still there. */
- }
-
- return p;
- }
-
- IritFatalError("Not Enough dynamic memory");
-
- return NULL; /* Make warnings silent. */
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Routine to free dynamic memory for all IRIT program/tool/libraries. M
- * All requests to free dynamic memory should invoke this function. M
- * If the environment variable "IRIT_MALLOC" is set when an IRIT program M
- * is executed, the consistency of the dynamic memory is tested on every M
- * invokation of this routine. See IritTestAllDynMemory function for more. M
- * *
- * PARAMETERS: M
- * p: Pointer to a block that needs to be freed. M
- * *
- * RETURN VALUE: M
- * void M
- * *
- * KEYWORDS: M
- * IritFree, allocation M
- *****************************************************************************/
- void IritFree(VoidPtr p)
- {
- if (IritDebugMalloc) {
- int i;
-
- if (*((long *) p) == OVERWRITE_STAMP_FREED)
- AllocError("Trying to free a free object again", p);
-
- if (p == NULL)
- AllocError("Free a NULL pointer", p);
-
- IritTestAllDynMemory(0);
-
- *((long *) p) = OVERWRITE_STAMP_FREED;
- p = ((char *) p) - 8;
-
- /* Compare the freed pointer with the list of allocated ones. */
- for (i = 0; i < AllocNumPtrs; i++) {
- if (AllocPtrTable[i] == p) {
- AllocPtrTable[i] = NULL;
- break;
- }
- }
-
- if (i >= AllocNumPtrs)
- AllocError("Free unallocated pointer", p);
- }
-
- #ifdef __DEBUG_TC_MALLOC__
- switch (heapcheck()) {
- case _HEAPCORRUPT:
- AllocError("Heap is corrupted", p);
- break;
- case _BADNODE:
- AllocError("Attempt to free a bogus pointer", p);
- break;
- case _FREEENTRY:
- AllocError("Attempt to free an already freed pointer", p);
- break;
- case _HEAPOK:
- case _HEAPEMPTY:
- case _USEDENTRY:
- break;
- default:
- AllocError("Allocation error", p);
- break;
-
- }
- #endif /* __DEBUG_TC_MALLOC__ */
-
- free(p);
- }
-