Borland Online And The Cobb Group Present:


October, 1995 - Vol. 2 No. 10


Listing A: DEBUGNEW.CPP


#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.