FixedAlloc::~FixedAlloc() { // Free all of the blocks while (m_firstBlock) { #ifdef MEMORY_INFO if(m_firstBlock->numAlloc > 0) { // go through every memory location, if the fourth 4 bytes cast as // an integer isn't 0xedededed then its allocated space and the integer is // an index into the stack trace table, the first 4 bytes will contain // the freelist pointer for free'd items (which is why the trace index is // stored in the second 4) // first 4 bytes - free list pointer // 2nd 4 bytes - alloc stack trace // 3rd 4 bytes - free stack trace // 4th 4 bytes - 0xedededed if freed correctly unsigned int *mem = (unsigned int*) m_firstBlock->items; unsigned int itemNum = 0; while(itemNum++ < m_itemsPerBlock) { unsigned int fourthInt = *(mem+3); if(fourthInt != 0xedededed) { GCDebugMsg(false, "Leaked %d byte item. Addr: 0x%x\n", GetItemSize(), mem+2); PrintStackTraceByIndex(*(mem+1)); } mem += (m_itemSize / sizeof(int)); } GCAssert(false); } // go through every item on the free list and make sure it wasn't written to // after being poisoned. void *item = m_firstBlock->firstFree; while(item) { #ifdef MMGC_64BIT for(int i=3, n=(m_firstBlock->size>>2)-3; i<n; i++) #else for(int i=3, n=(m_firstBlock->size>>2)-1; i<n; i++) #endif { unsigned int data = ((int*)item)[i]; if(data != 0xedededed) { GCDebugMsg(false, "Object 0x%x was written to after it was deleted, allocation trace:"); PrintStackTrace((int*)item+2); GCDebugMsg(false, "Deletion trace:"); PrintStackTrace((int*)item+3); GCDebugMsg(true, "Deleted item write violation!"); } } // next free item item = *((void**)item); } #endif FreeChunk(m_firstBlock); } }
void RCObject::DumpHistory() { GCDebugMsg(false, "Ref count modification history for object 0x%x:\n", this); int *traces = history.GetData(); for(int i=0, n=history.Count(); i<n; i++) { PrintStackTraceByIndex(traces[i]); } }
void GCDebugMsg(bool debugBreak, const char* format, ...) { char buf[1024]; va_list args; va_start(args, format); VMPI_vsnprintf(buf, sizeof(buf), format, args); // Belt and suspenders, remove when we're sure VMPI_vsnprintf is completely reliable buf[sizeof(buf)-2] = '\n'; buf[sizeof(buf)-1] = '\0'; va_end(args); GCDebugMsg(buf, debugBreak); }
void GCDebugMsg(bool debuggerBreak, const char *format, ...) { // [ggrossman 09.24.04] // Changed this to _DEBUG only because we don't link to // CRT in Release builds, so vsprintf is unavailable!! #if defined (_DEBUG) && !defined(UNDER_CE) va_list argptr; va_start(argptr, format); int bufferSize = _vscprintf(format, argptr)+1; char *buffer = (char*)alloca(bufferSize+2); if (buffer) { StringCbVPrintf(buffer, bufferSize+1, format, argptr); GCDebugMsg(buffer, debuggerBreak); } #else (void)debuggerBreak; (void)format; #endif }