1: 
   2: 
   3: #include <cstdio> 
   4: #include <cstdlib> 
   5: #include <cstring> 
   6: 
   7: #include "wwwi/mutex.h" 
   8: #include "wwwi/os.h" 
   9: 
  10: enum new_type_enum { NEW_SIMPLE, NEW_ARRAY };
  11: typedef enum new_type_enum NewType;
  12: 
  13: const unsigned _wwwi_magic = 0xdeadc0de;
  14: 
  15: #ifdef WWWI_QNX 
  16: const unsigned _wwwi_leftover = 15;
  17: #endif 
  18: #ifdef freebsd 
  19: const unsigned _wwwi_leftover = 3;
  20: #endif 
  21: 
  22: struct mem_footer_struct {
  23:   unsigned uMagic;
  24: };
  25: typedef struct mem_footer_struct MemFooter;
  26: typedef MemFooter* MemFooterPtr;
  27: 
  28: struct mem_header_struct {
  29:   unsigned     uMagic0;
  30:   bool         bAllocated;
  31:   NewType      newType;
  32:   MemFooterPtr memFooterPtr;
  33:   size_t       szAlloc;
  34:   unsigned     uMagic1;
  35: };
  36: typedef struct mem_header_struct MemHeader;
  37: typedef MemHeader* MemHeaderPtr;
  38: 
  39: using namespace std;
  40: 
  41: void _wwwi_atexit(void);
  42: void _wwwi_free(void*,NewType);
  43: void _wwwi_init(void);
  44: void *_wwwi_malloc(size_t,NewType);
  45: void _wwwi_table_add(MemHeaderPtr);
  46: void _wwwi_table_remove(MemHeaderPtr);
  47: 
  48: unsigned _wwwi_count = 0;
  49: MemHeaderPtr *_wwwi_table = NULL;
  50: unsigned _wwwi_table_size = 0;
  51: 
  52: void *operator new(size_t i_szAlloc) {
  53:   return _wwwi_malloc(i_szAlloc,NEW_SIMPLE);
  54: }
  55: 
  56: void *operator new[](size_t i_szAlloc) {
  57:   return _wwwi_malloc(i_szAlloc,NEW_ARRAY);
  58: }
  59: 
  60: 
  61: void *_wwwi_malloc(size_t i_szAlloc, NewType newType) {
  62:   static bool bInit = false;
  63:   if (bInit==false) {
  64:     _wwwi_init();
  65:     bInit = true;
  66:   }
  67:   size_t szAdjusted = i_szAlloc + sizeof(MemHeader) + sizeof(MemFooter);
  68:   char *pcMalloc = (char*)malloc(szAdjusted);
  69:   if (pcMalloc==NULL) {
  70:     fprintf(stderr,"malloc() failed\n");
  71:     abort();
  72:   }
  73:   MemHeaderPtr mhp = (MemHeaderPtr)pcMalloc;
  74:   pcMalloc = (char*)(mhp+1);
  75:   MemFooterPtr mfp = (MemFooterPtr)(pcMalloc+i_szAlloc);
  76: 
  77:   mhp->uMagic0 = _wwwi_magic;
  78:   mhp->bAllocated = true;
  79:   mhp->newType = newType;
  80:   mhp->memFooterPtr = mfp;
  81:   mhp->szAlloc = i_szAlloc;
  82:   mhp->uMagic1 = _wwwi_magic;
  83:   mfp->uMagic = _wwwi_magic;
  84:   _wwwi_table_add(mhp);
  85:   
  86:   //fprintf(stderr,"new %d (%d) bytes at %08X (mhp %08X mfp %08X)\n",i_szAlloc,szAdjusted,(unsigned)pcMalloc,(unsigned)mhp,(unsigned)mfp);
  87:   _wwwi_count++;
  88:   return pcMalloc;
  89: }
  90: 
  91: void operator delete(void *pv) {
  92:   _wwwi_free(pv,NEW_SIMPLE);
  93: }
  94: 
  95: 
  96: void operator delete[](void *pv) {
  97:   _wwwi_free(pv,NEW_ARRAY);
  98: }
  99: 
 100: 
 101: void _wwwi_free(void *pv, NewType newType) {
 102:   if (pv==NULL) return;  // This makes me sick, but QNX requires it.
 103:   MemHeaderPtr mhp = ((MemHeaderPtr)pv) - 1;
 104:   if(mhp->uMagic0!=_wwwi_magic) {
 105:     fprintf(stderr,"delete: invalid pointer\n");
 106:     abort();
 107:   }
 108:   if(mhp->uMagic1!=_wwwi_magic) {
 109:     fprintf(stderr,"delete: block %08X stepped under bounds\n",(unsigned)pv);
 110:     abort();
 111:   }
 112:   if(mhp->bAllocated==false) {
 113:     fprintf(stderr,"delete: block %08X already freed\n",(unsigned)pv);
 114:     abort();
 115:   }
 116:   mhp->bAllocated = false;
 117:   if(mhp->newType!=newType) {
 118:     fprintf(stderr,"delete: block %08X allocated with %s but freed with %s\n",(unsigned)pv,((mhp->newType==NEW_SIMPLE)?"new":"new[]"),((newType==NEW_SIMPLE)?"new":"new[]"));
 119:     abort();
 120:   }
 121:   if(mhp->memFooterPtr->uMagic!=_wwwi_magic) {
 122:     fprintf(stderr,"delete: block %08X stepped over bounds\n",(unsigned)pv);
 123:     abort();
 124:   }
 125:   //fprintf(stderr,"delete %u at %08X\n",(unsigned)mhp->szAlloc,(unsigned)pv);
 126:   if (_wwwi_count==0) {
 127:     fprintf(stderr,"delete: more blocks deleted than allocated\n");
 128:     abort();
 129:   }
 130:   _wwwi_count--;
 131:   _wwwi_table_remove(mhp);
 132:   memset(pv,0xcc,mhp->szAlloc);
 133:   free((void*)mhp);
 134: }
 135: 
 136: 
 137: void _wwwi_init() {
 138:   fprintf(stderr,"WWWI debugging allocator in use\n");
 139:   if (atexit(_wwwi_atexit)!=0) {
 140:     fprintf(stderr,"_wwwi_init: atexit() failed\n");
 141:     abort();
 142:   }
 143:   _wwwi_table_size = 32;
 144:   _wwwi_table = (MemHeaderPtr*)malloc(sizeof(MemHeaderPtr)*_wwwi_table_size);
 145:   if (_wwwi_table==NULL) {
 146:     fprintf(stderr,"_wwwi_init: could not allocate malloc table\n");
 147:     abort();
 148:   }
 149:   memset(_wwwi_table,0,sizeof(MemHeaderPtr)*_wwwi_table_size);
 150: 
 151: }
 152: 
 153: 
 154: void _wwwi_atexit() {
 155:   unsigned u;
 156:   if (_wwwi_count!=0) {
 157:     fprintf(stderr,"_wwwi_atexit: %u blocks were not deleted, %u is normal\n",_wwwi_count,_wwwi_leftover);
 158:   }
 159:   for(u=0;u<_wwwi_table_size;u++) {
 160:     if (_wwwi_table[u]==NULL) continue;
 161:     fprintf(stderr,"block not freed: %u bytes at %08X\n",_wwwi_table[u]->szAlloc,(unsigned)(_wwwi_table[u]+1));
 162:   }
 163: }
 164: 
 165: 
 166: void _wwwi_table_add(MemHeaderPtr i_mhp) {
 167:   unsigned u;
 168:   MemHeaderPtr *mhpTableNew;
 169:   for(u=0;u<_wwwi_table_size;u++) {
 170:     if (_wwwi_table[u]!=NULL) continue;
 171:     _wwwi_table[u] = i_mhp;
 172:     return;
 173:   }
 174:   _wwwi_table_size *= 2;
 175:   mhpTableNew = (MemHeaderPtr*)realloc(_wwwi_table,sizeof(MemHeaderPtr)*_wwwi_table_size);
 176:   if(mhpTableNew==NULL) {
 177:     fprintf(stderr,"_wwwi_add_table: table grow to %u failed\n",_wwwi_table_size);
 178:     abort();
 179:   }
 180:   _wwwi_table = mhpTableNew;
 181:   for(u=_wwwi_table_size/2;u<_wwwi_table_size;u++) _wwwi_table[u] = NULL;
 182:   fprintf(stderr,"_wwwi_add_table: table grows to %u\n",_wwwi_table_size);
 183:   _wwwi_table[_wwwi_table_size/2] = i_mhp;
 184: }
 185: 
 186: 
 187: void _wwwi_table_remove(MemHeaderPtr i_mhp) {
 188:   unsigned u;
 189:   for(u=0;u<_wwwi_table_size;u++) {
 190:     if (_wwwi_table[u]!=i_mhp) continue;
 191:     _wwwi_table[u] = NULL;
 192:     return;
 193:   }
 194:   fprintf(stderr,"_wwwi_table_remove: block not in table\n");
 195:   abort();
 196: }
 197: 
 198: 
 199: