#include <new.h> #include <stdio.h> #define __TRACE #define __WARN #include <checks.h> typedef unsigned char guardType; typedef size_t blockSizeType; typedef unsigned long int idNumberType; enum dynamicOperation {NewObject, NewArray, DelObject, DelArray}; extern new_handler _new_handler; int flag = 0; idNumberType AllocationCount = 1; const unsigned char guardValue = 0xe1; blockSizeType * blockSize; guardType * preGuard; char * allocPtr; void * debugPtr = 0; guardType * postGuard; idNumberType * idNumber; dynamicOperation * operation; dynamicOperation oldOperation; void setPointers(void* location, size_t size) { (char*)blockSize = (char*)location; (char*)preGuard = (char*)blockSize + sizeof(*blockSize); (char*)allocPtr = (char*)preGuard + sizeof(*preGuard); (char*)postGuard = allocPtr + size; (char*)idNumber = (char*)postGuard + sizeof(*postGuard); (char*)operation = (char*)idNumber + sizeof(*idNumber); } void writePointers() { FILE* LogFile; if(flag == 0) { flag = 1; LogFile = fopen("memtest.log", "wb"); } else { LogFile = fopen("memtest.log", "ab"); } fwrite(idNumber, sizeof(*idNumber), 1, LogFile); fwrite(blockSize, sizeof(*blockSize), 1, LogFile); fwrite(operation, sizeof(*operation), 1, LogFile); fclose(LogFile); } void setSizeAndAlloc(size_t size) { size = size ? size : 1; size_t debugSize = sizeof(*blockSize) + sizeof(*preGuard) + size + sizeof(*postGuard) + sizeof(*idNumber) + sizeof(*operation); while ( (debugPtr = malloc(debugSize)) == NULL && _new_handler != NULL ) _new_handler(); setPointers(debugPtr, size); *blockSize = size; *preGuard = guardValue; *postGuard = guardValue; *idNumber = AllocationCount++; } void * operator new(size_t size) { setSizeAndAlloc(size); *operation = NewObject; writePointers(); return allocPtr; } void * operator new[](size_t size) { setSizeAndAlloc(size); *operation = NewArray; writePointers(); return allocPtr; } int validatePointer(void * pointer) { preGuard = (unsigned char*)pointer - sizeof(*preGuard); if(*preGuard != guardValue) { TRACE("Pre-guard error or invalid pointer - " << (unsigned int)guardValue << " -> " << (unsigned int)*preGuard); return 0; } (char*)blockSize = (char*)pointer - sizeof(*preGuard) - sizeof(*blockSize); pointer = blockSize; setPointers(pointer, *blockSize); oldOperation = *operation; return 1; } void displayWarnings() { WARN((*postGuard != guardValue), "Post-guard error - " << (unsigned int)guardValue << " -> " << (unsigned int)*postGuard); if(*operation == DelArray) { WARN((oldOperation == DelArray), "Deleting pointer twice"); WARN((oldOperation == DelObject), "Passing a deleted object to delete[]"); WARN((oldOperation == NewObject), "Passing an object to delete[]"); } else { WARN((oldOperation == DelObject), "Deleting pointer twice"); WARN((oldOperation == DelArray), "Passing a deleted array to delete"); WARN((oldOperation == NewArray), "Passing an array to delete"); } TRACE("Delete error on id#" << *idNumber); TRACE("Size(" << *blockSize << ")"); } void operator delete(void* dyingPtr) { if(validatePointer(dyingPtr)) { *operation = DelObject; if((oldOperation == NewObject) && (*postGuard == guardValue)) { writePointers(); free((char*)blockSize); } else { writePointers(); displayWarnings(); } } } void operator delete[](void* dyingPtr) { if(validatePointer(dyingPtr)) { *operation = DelArray; if((oldOperation == NewArray) && (*postGuard == guardValue)) { writePointers(); free((char*)blockSize); } else { writePointers(); displayWarnings(); } } }
Return to "Debugging dynamic memory allocations in C"
Copyright (c) 1996 The Cobb Group, a division of Ziff-Davis Publishing Company. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of Ziff-Davis Publishing Company is prohibited. The Cobb Group and The Cobb Group logo are trademarks of Ziff-Davis Publishing Company.