#include #include #include #define DBG_HEAP_ME_MYSELF_I #include typedef struct _BLKINFO { /* Memory block info */ int usTag; /* Identifier */ size_t size; /* Size of allocated block */ struct _BLKINFO *pNext ; /* Next memory block */ struct _BLKINFO *pPrev ; /* Previous memory block */ char achFile[_MAX_PATH]; /* File name of allocator */ int usLine; /* Line number of allocator */ } BLKINFO, *PBLKINFO; #define BLOCK_TAG 0xa55a /* BLKINFO tag */ #define PROTECT_SIZE 5 /* Size of protected area */ #define PROTECT_TAG 0x5a /* Header and footer protection tag */ #define CLIENT_OFFSET (sizeof(BLKINFO) + PROTECT_SIZE) #define PINFOFROMCLIENT(a) ((PBLKINFO) (((char *)(a)) - CLIENT_OFFSET)) #define CLIENTFROMPINFO(a) ((void *) (((char *)(a)) + CLIENT_OFFSET)) static void AddToList(PBLKINFO p); static void RemoveFromList(PBLKINFO p); static void DbgTagError(PBLKINFO p, char *pszFile, int usLine); /************************************************************************/ /* */ /* */ /************************************************************************/ void *DbgMalloc(size_t size, char *pszFile, int usLine) { PBLKINFO p; p = malloc(CLIENT_OFFSET + size + PROTECT_SIZE); p->usTag = BLOCK_TAG; p->size = size; strcpy(p->achFile, pszFile); p->usLine = usLine; memset((char *)CLIENTFROMPINFO(p) - PROTECT_SIZE, PROTECT_TAG, PROTECT_SIZE); memset((char *)CLIENTFROMPINFO(p) + size , PROTECT_TAG, PROTECT_SIZE); AddToList(p); return(CLIENTFROMPINFO(p)); } /************************************************************************/ /* IsHeadOK */ /* */ /* Checks header consistancy. Returns TRUE if OK, FALSE otherwise. */ /************************************************************************/ static int IsHeadOK(PBLKINFO p) { int i = PROTECT_SIZE; char *pProt = (char *)p + sizeof(BLKINFO); while(i--) if(*pProt++ != PROTECT_TAG) return(0); return(1); } /************************************************************************/ /* IsFootOK */ /* */ /* Checks footer consistancy. Returns 1 if OK, 0 otherwise. */ /************************************************************************/ static int IsFootOK(PBLKINFO p) { int i = PROTECT_SIZE; char *pProt = (char *)p + CLIENT_OFFSET + p->size; while(i--) if(*pProt++ != PROTECT_TAG) return(0); return(1); } /************************************************************************/ /* */ /* */ /************************************************************************/ void *DbgRealloc(void *ptr, size_t size, char *pszFile, int usLine) { PBLKINFO p = PINFOFROMCLIENT(ptr); /* * Check for consistancy */ if(p->usTag != BLOCK_TAG || !IsHeadOK(p) || !IsFootOK(p)) { DbgTagError(p, pszFile, usLine); abort(); } /* * Invalidate memory */ p->usTag = ~BLOCK_TAG; RemoveFromList(p); p = realloc(p, CLIENT_OFFSET + PROTECT_SIZE + size); p->usTag = BLOCK_TAG; p->size = size; strcpy(p->achFile, pszFile); p->usLine = usLine; memset((char *)CLIENTFROMPINFO(p) - PROTECT_SIZE, PROTECT_TAG, PROTECT_SIZE); memset((char *)CLIENTFROMPINFO(p) + size , PROTECT_TAG, PROTECT_SIZE); AddToList(p); return(CLIENTFROMPINFO(p)); } /************************************************************************/ /* */ /* */ /************************************************************************/ void *DbgStrdup(char *psz, char *pszFile, int usLine) { return(strcpy(DbgMalloc(strlen(psz) + 1, pszFile, usLine), psz)); } /************************************************************************/ /* */ /* */ /************************************************************************/ void DbgFree(void *ptr, char *pszFile, int usLine) { PBLKINFO p = PINFOFROMCLIENT(ptr); /* * Check for consistancy */ if(p->usTag != BLOCK_TAG || !IsHeadOK(p) || !IsFootOK(p)) { DbgTagError(p, pszFile, usLine); free(ptr); } else { /* * Invalidate memory */ p->usTag = ~BLOCK_TAG; RemoveFromList(p); } } /************************************************************************/ /* */ /* */ /************************************************************************/ static PBLKINFO pBlkRoot = NULL; static void AddToList(PBLKINFO p) { lprintf("%s(%u) : %u Bytes belegt", p->achFile, p->usLine, p->size); p->pNext = pBlkRoot; p->pPrev = NULL; if(pBlkRoot != NULL) pBlkRoot->pPrev = p; pBlkRoot = p; } static void RemoveFromList(PBLKINFO p) { lprintf("%s(%u) : %u Bytes freigegeben", p->achFile, p->usLine, p->size); if(p->pNext != NULL) p->pNext->pPrev = p->pPrev; if(p->pPrev != NULL) p->pPrev->pNext = p->pNext; else pBlkRoot = p->pNext; } /************************************************************************/ /* */ /* */ /************************************************************************/ static void DbgTagError(PBLKINFO p, char *pszFile, int usLine) { if (p->usTag != BLOCK_TAG) lprintf("%s(%u) : Verwaltungsblock zerst”rt", pszFile, usLine); else if(!IsHeadOK(p)) lprintf("%s(%u) : Speicherbeginn verletzt seit %s %u", pszFile, usLine, p->achFile, p->usLine); else if(!IsFootOK(p)) lprintf("%s(%u) : Speicherende verletzt seit %s %u", pszFile, usLine, p->achFile, p->usLine); } /************************************************************************/ /* */ /* */ /************************************************************************/ int DbgHeapDump(void) { int fResult = 1; long ulSum = 0L; PBLKINFO p; lprintf("-------------------------------------"); p = pBlkRoot; while(p != NULL) { if (p->usTag != BLOCK_TAG) { lprintf("%s(%u) : Verwaltungsblock zerst”rt", p->achFile, p->usLine); fResult = 0; } else if(!IsHeadOK(p)) { lprintf("%s(%u) : Speicherbeginn verletzt", p->achFile, p->usLine); fResult = 0; } else if(!IsFootOK(p)) { lprintf("%s(%u) : Speicherende verletzt", p->achFile, p->usLine); fResult = 0; } else { lprintf("%s(%u) : %u Bytes belegt", p->achFile, p->usLine, p->size); ulSum += p->size; } p = p->pNext; } lprintf("Insgesamt %lu Bytes belegt --------", ulSum); return(fResult); }