bool EnableLowFragmentationHeap() { HMODULE kernel32 = GetModuleHandle(L"kernel32.dll"); HeapSetFn heap_set = reinterpret_cast<HeapSetFn>(GetProcAddress( kernel32, "HeapSetInformation")); // On Windows 2000, the function is not exported. This is not a reason to // fail. if (!heap_set) return true; unsigned number_heaps = GetProcessHeaps(0, NULL); if (!number_heaps) return false; // Gives us some extra space in the array in case a thread is creating heaps // at the same time we're querying them. static const int MARGIN = 8; scoped_ptr<HANDLE[]> heaps(new HANDLE[number_heaps + MARGIN]); number_heaps = GetProcessHeaps(number_heaps + MARGIN, heaps.get()); if (!number_heaps) return false; for (unsigned i = 0; i < number_heaps; ++i) { ULONG lfh_flag = 2; // Don't bother with the result code. It may fails on heaps that have the // HEAP_NO_SERIALIZE flag. This is expected and not a problem at all. heap_set(heaps[i], HeapCompatibilityInformation, &lfh_flag, sizeof(lfh_flag)); } return true; }
HIDDEN void TSTRACEValidateHeaps() { #ifdef DEBUG_HEAP if ( _heapchk() != _HEAPOK ) { CkmError("***** HEAP DAMAGE DETECTED *****"); LOG(CallTrace, "Error: ***** HEAP DAMAGE DETECTED *****"); DebugBreak(); } #endif #ifdef DEBUG_PROCESS_HEAP tsByteString buffer; DWORD heapCount; buffer.resize (sizeof(HANDLE)); heapCount = GetProcessHeaps(1, (PHANDLE)buffer.rawData()); if ( heapCount > 1 ) { buffer.resize(sizeof(HANDLE) * heapCount); heapCount = GetProcessHeaps(heapCount, (PHANDLE)buffer.rawData()); } for (int ii = 0; ii < heapCount; ii++) { if ( !HeapValidate(((PHANDLE)buffer.rawData())[ii], 0, NULL) ) { CkmError("***** PROCESS HEAP DAMAGE DETECTED *****"); LOG(CallTrace, "Error: ***** PROCESS HEAP DAMAGE DETECTED *****"); // DebugBreak(); } } #endif // DEBUG_PROCESS_HEAP }
//-------------------------------------------------------------------// // CompactHeap() // //-------------------------------------------------------------------// // This function compacts the application's heap(s) and returns // the maximum block size available after compaction. // // Not sure which of the heaps we encounter is the "default" used by // the program. We compact them all. // // If you want a heap count, provide the address of the integer // to set. // // NOTE: we only allow 25 heaps max here. //-------------------------------------------------------------------// unsigned int CompactHeap( int* pnHeapCount ) { // This does ALL heaps. unsigned int unLargestBlock = 0; HANDLE hHeaps[25]; DWORD dwHeaps = GetProcessHeaps( 25, hHeaps ); ASSERT( dwHeaps < 25 ); if ( dwHeaps < 25 ) { for ( int nA = 0; nA < dwHeaps; nA++ ) { unLargestBlock = max( unLargestBlock, HeapCompact( hHeaps[nA], 0 ) ); } } if ( pnHeapCount != 0 ) *pnHeapCount = dwHeaps; return unLargestBlock; /* // This does the default heap (the CRT heap? not according to // M$DN support...). return HeapCompact( GetProcessHeap(), 0 ); */ }
BOOL My_GetProcessHeaps() { DWORD NumberOfHeaps=NULL; PHANDLE ProcessHeaps=NULL; DWORD returnVal_Real = NULL; DWORD returnVal_Intercepted = NULL; DWORD error_Real = 0; DWORD error_Intercepted = 0; __try{ disableInterception(); returnVal_Real = GetProcessHeaps (NumberOfHeaps,ProcessHeaps); error_Real = GetLastError(); enableInterception(); returnVal_Intercepted = GetProcessHeaps (NumberOfHeaps,ProcessHeaps); error_Intercepted = GetLastError(); }__except(puts("in filter"), 1){puts("exception caught");} return ((returnVal_Real == returnVal_Intercepted) && (error_Real == error_Intercepted)); }
void CHECKHEAP() // Validate all the heaps in this process { HANDLE rgHeap[100]; DWORD cHeap = GetProcessHeaps(100, rgHeap); ASSERT(cHeap > 0 && cHeap <= 100); for (ULONG iHeap=0; iHeap<cHeap; iHeap++) { ASSERT(HeapValidate(rgHeap[iHeap],0,NULL)); } }
void FF13Plugin::initialize(unsigned rw, unsigned rh, D3DFORMAT bbformat, D3DFORMAT dssformat) { GenericPlugin::initialize(rw, rh, bbformat, dssformat); // Force low fragmentation heap HANDLE heaps[128]; DWORD numHeaps = GetProcessHeaps(128, heaps); for(DWORD i = 0; i < numHeaps; ++i) { ULONG HeapInformation = HEAP_LFH; BOOL res = HeapSetInformation(heaps[i], HeapCompatibilityInformation, &HeapInformation, sizeof(HeapInformation)); if(res != FALSE) { SDLOG(1, "Low-fragmentation heap enabled for heap #%d.\n", i); } else { SDLOG(1, "Failed to enable low-fragmentation for heap #%d; LastError %d.\n", i, GetLastError()); } } }
void forceLFHs() { // Force low fragmentation heap SDLOG(2, "Starting heap adjustment (LFH)\n"); HANDLE heaps[256]; DWORD numHeaps = GetProcessHeaps(256, heaps); for(DWORD i = 0; i < numHeaps; ++i) { ULONG HeapInformation = HEAP_LFH; BOOL res = HeapSetInformation(heaps[i], HeapCompatibilityInformation, &HeapInformation, sizeof(HeapInformation)); if(res != FALSE) { SDLOG(1, "Low-fragmentation heap enabled for heap #%d.\n", i); } else { SDLOG(1, "Failed to enable low-fragmentation for heap #%d; LastError %d.\n", i, GetLastError()); } } SDLOG(2, "Completed heap adjustment (LFH)\n"); }
void print_rusage (void) { #if defined(WIN32) //int i; static SIZE_T previous = 0; DWORD minWSS, maxWSS; GetProcessWorkingSetSize (GetCurrentProcess(), &minWSS, &maxWSS); #if 0 const DWORD maxH = 100; HANDLE heaps[maxH], nbrh; nbrh = GetProcessHeaps (maxH, heaps); if (nbrh > maxH) nbrh = maxH; unsigned long hsize = 0; for (i = 0; i < nbrh; ++i) hsize += HeapSize (heaps[i], 0, heaps[i]); MEMORY_BASIC_INFORMATION mbi; mbi.RegionSize = 1234; if (VirtualQuery (NULL, &mbi, sizeof(mbi)) != sizeof(mbi)) { } printf ("RUSAGE: VQ=%ld minWSS=%ld maxWSS=%ld\n", mbi.RegionSize, minWSS, maxWSS); #endif PROCESS_MEMORY_COUNTERS PMC; memset(&PMC, 0, sizeof(PMC)); // Set size of structure PMC.cb = sizeof(PMC); // Get memory usage GetProcessMemoryInfo(GetCurrentProcess(), &PMC, sizeof(PMC)); printf ("RUSAGE: PFU += %6ld kb peakPFU=%3ld.%03ld peakWSS=%3ld.%03ld (Mbytes)\n", (PMC.PeakPagefileUsage-previous)/1024, PMC.PeakPagefileUsage/(1024*1024), (PMC.PeakPagefileUsage%(1024*1024))/1000, PMC.PeakWorkingSetSize/(1024*1024), (PMC.PeakWorkingSetSize%(1024*1024))/1000); previous = PMC.PeakPagefileUsage; #endif }
void KMemDump::Dump(unsigned char * start, unsigned offset, int size, int unitsize) { if ( offset==0 ) { HANDLE hHeaps[10]; int no = GetProcessHeaps(10, hHeaps); // walk the heap if it is a heap for (int i=0; i<no; i++) if ( start == hHeaps[i] ) { PROCESS_HEAP_ENTRY entry; entry.lpData = NULL; while ( HeapWalk(start, & entry) ) { wsprintf(m_line, "%x %d+%d bytes %x\r\n", entry.lpData, entry.cbData, entry.cbOverhead, entry.iRegionIndex); * m_stream << m_line; } * m_stream << "\r\n"; break; } } * m_stream << size; * m_stream << " bytes\n"; while (size>0) { DumpLine(start, offset, unitsize); start += 16; size -= 16; * m_stream << m_line; } }
int APIENTRY WINMAIN(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { const S32 MAX_HEAPS = 255; DWORD heap_enable_lfh_error[MAX_HEAPS]; S32 num_heaps = 0; #if WINDOWS_CRT_MEM_CHECKS && !INCLUDE_VLD _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); // dump memory leaks on exit #elif 1 // Experimental - enable the low fragmentation heap // This results in a 2-3x improvement in opening a new Inventory window (which uses a large numebr of allocations) // Note: This won't work when running from the debugger unless the _NO_DEBUG_HEAP environment variable is set to 1 _CrtSetDbgFlag(0); // default, just making explicit ULONG ulEnableLFH = 2; HANDLE* hHeaps = new HANDLE[MAX_HEAPS]; num_heaps = GetProcessHeaps(MAX_HEAPS, hHeaps); for(S32 i = 0; i < num_heaps; i++) { bool success = HeapSetInformation(hHeaps[i], HeapCompatibilityInformation, &ulEnableLFH, sizeof(ulEnableLFH)); if (success) heap_enable_lfh_error[i] = 0; else heap_enable_lfh_error[i] = GetLastError(); } #endif // *FIX: global gIconResource = MAKEINTRESOURCE(IDI_LL_ICON); LLAppViewerWin32* viewer_app_ptr = new LLAppViewerWin32(lpCmdLine); viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash); // Set a debug info flag to indicate if multiple instances are running. bool found_other_instance = !create_app_mutex(); gDebugInfo["FoundOtherInstanceAtStartup"] = LLSD::Boolean(found_other_instance); bool ok = viewer_app_ptr->init(); if(!ok) { llwarns << "Application init failed." << llendl; return -1; } // Have to wait until after logging is initialized to display LFH info if (num_heaps > 0) { llinfos << "Attempted to enable LFH for " << num_heaps << " heaps." << llendl; for(S32 i = 0; i < num_heaps; i++) { if (heap_enable_lfh_error[i]) { llinfos << " Failed to enable LFH for heap: " << i << " Error: " << heap_enable_lfh_error[i] << llendl; } } } // Run the application main loop if(!LLApp::isQuitting()) { viewer_app_ptr->mainLoop(); } if (!LLApp::isError()) { // // We don't want to do cleanup here if the error handler got called - // the assumption is that the error handler is responsible for doing // app cleanup if there was a problem. // #if WINDOWS_CRT_MEM_CHECKS llinfos << "CRT Checking memory:" << llendflush; if (!_CrtCheckMemory()) { llwarns << "_CrtCheckMemory() failed at prior to cleanup!" << llendflush; } else { llinfos << " No corruption detected." << llendflush; } #endif gGLActive = TRUE; viewer_app_ptr->cleanup(); #if WINDOWS_CRT_MEM_CHECKS llinfos << "CRT Checking memory:" << llendflush; if (!_CrtCheckMemory()) { llwarns << "_CrtCheckMemory() failed after cleanup!" << llendflush; } else { llinfos << " No corruption detected." << llendflush; } #endif } delete viewer_app_ptr; viewer_app_ptr = NULL; //start updater if(LLAppViewer::sUpdaterInfo) { _spawnl(_P_NOWAIT, LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), LLAppViewer::sUpdaterInfo->mParams.str().c_str(), NULL); delete LLAppViewer::sUpdaterInfo ; LLAppViewer::sUpdaterInfo = NULL ; } return 0; }
void KSnapShot::Shot(KListView * list) { unsigned char * start = NULL; MEMORY_BASIC_INFORMATION info; KPEFile module; void * lastmodule = NULL; typedef enum { nMaxHeaps = 10 }; HANDLE ProcHeaps[nMaxHeaps]; int heaps = GetProcessHeaps(nMaxHeaps, ProcHeaps); while ( VirtualQuery(start, & info, sizeof(info)) ) { KRegion * pRegion = NULL; // compute CRC for committed region if (info.State == MEM_COMMIT) { pRegion = FindRegion(start, info.RegionSize); if (pRegion) { pRegion->type = info.Type; pRegion->lastcrc = pRegion->crc; pRegion->crc = m_crc.Update(0, start, info.RegionSize); pRegion->count ++; } } if (list) { TCHAR temp[MAX_PATH]; const TCHAR * p ; if ( pRegion && pRegion->count>=2 ) { wsprintf(temp, "%04x", pRegion->lastcrc); list->AddItem(0, temp, ( pRegion->lastcrc != pRegion->crc ) + 1); } else list->AddItem(0, " ", 0); if ( pRegion ) { wsprintf(temp, "%04x", pRegion->crc); list->AddItem(1, temp); } wsprintf(temp, "%08lx", info.BaseAddress); list->AddItem(2, temp); wsprintf(temp, "%08lx", info.RegionSize); list->AddItem(3, temp); switch (info.State) { case MEM_FREE: p = "F "; break; case MEM_RESERVE: p = "R "; break; case MEM_COMMIT: p = "C "; break; default: p = "? "; } strcpy(temp, p); if ( info.State != MEM_FREE) { switch (info.Type) { case MEM_IMAGE: p = "I "; break; case MEM_MAPPED: p = "M "; break; case MEM_PRIVATE: p = "P "; break; default: p = "? "; } strcat(temp, p); AddFlags(temp, info.AllocationProtect, Protections, sizeof(Protections)/sizeof(Protections[0])); } list->AddItem(4, temp); /* char t[MAX_PATH]; wsprintf(t, "%8lx ", info.AllocationBase); strcat(temp, t); if (info.State != MEM_RESERVE) AddFlags(temp, info.Protect, Protections, sizeof(Protections)/sizeof(Protections[0])); */ if (info.State != MEM_FREE ) if ( GetModuleFileName((HINSTANCE) info.BaseAddress, temp, sizeof(temp)) ) { if (lastmodule) { module.Unload(); lastmodule = NULL; } if ( module.Load(temp) ) lastmodule = info.BaseAddress; // remove the directory path, keep only the filename if ( strchr(temp, '\\') ) { for (char *p = strchr(temp, '\\') + 1; strchr(p, '\\'); p = strchr(p, '\\') + 1); list->AddItem(5, p); } else list->AddItem(5, temp); } else { const char * p = NULL; if (lastmodule != NULL) p = module.GetSectionName((unsigned) info.BaseAddress - (unsigned) lastmodule); if (p == NULL) for (int h=0; h<heaps; h++) if ( info.BaseAddress == ProcHeaps[h] ) { wsprintf(temp, "Heap %d", h+1); p = temp; break; } if (p == NULL) if ( ( (unsigned) (& p) >= (unsigned) info.BaseAddress ) && ( (unsigned) (& p) < (unsigned) info.BaseAddress + info.RegionSize ) ) p = "Stack"; if ( p ) list->AddItem(5, p); } } start += info.RegionSize; if (start == 0) break; } if (lastmodule) module.Unload(); }
void SaveHeapLog() { FILE *f; _HEAPINFO hi; char block[129],*ad; block[128]=0; int code; HANDLE heaps[200]; DWORD n; PROCESS_HEAP_ENTRY phe; f=fopen(WriteDir+SLASH+"heap.log","wb"); SetLastError(0); n=GetProcessHeaps(200,heaps); heaps[n]=GetProcessHeap();n++; fprintf(f,"There are %i heaps for Steem\r\n",n); for (DWORD i=0;i<n;i++){ code=HeapValidate(heaps[i],0,NULL); if (code){ fprintf(f,"Heap %u okay\r\n",i); }else{ fprintf(f,"Heap %u has an error in it!\r\n",i); } HeapLock(heaps[i]); phe.lpData=NULL; while (HeapWalk(heaps[i],&phe)){ fprintf(f,"%s%X\r\n","Bad node, address=",(unsigned long)(phe.lpData)); ad=((char*)phe.lpData)-64; for (int n=0;n<128;n++){ block[n]=*(ad++); if (block[n]==0) block[n]='\\'; if (block[n]==10) block[n]='\\'; if (block[n]==13) block[n]='\\'; } fprintf(f,"%s\r\n",block); } HeapUnlock(heaps[i]); if (phe.lpData==NULL) DisplayLastError(); } fprintf(f,"\r\n\r\n"); code=_heapchk(); if (code==_HEAPOK){ fprintf(f,"%s\r\n","Heap okay, walking:"); }else if (code==_HEAPBADNODE){ fprintf(f,"%s\r\n","Heap has bad node! Walking anyway:"); } hi._pentry=NULL; for(;;){ code=_rtl_heapwalk(&hi); if (code==_HEAPEND) break; if (code==_HEAPBADNODE){ fprintf(f,"%s%X\r\n","Bad node, address=",(unsigned long)(hi.__pentry)); ad=((char*)hi._pentry)-64; for (int n=0;n<128;n++){ block[n]=*(ad++); if (block[n]==0) block[n]='\\'; if (block[n]==10) block[n]='\\'; if (block[n]==13) block[n]='\\'; } fprintf(f,"%s\r\n",block); }else if (code==_HEAPOK){ fprintf(f,"%s%X\r\n","Good node, address=",(unsigned long)(hi.__pentry)); } } fclose(f); }
void CCompInfo::GetHeaps() { memset(m_aHeaps,0,sizeof(m_aHeaps)); m_nHeaps = GetProcessHeaps(sizeof(m_aHeaps)/sizeof(m_aHeaps[0]),m_aHeaps); };
DWORD prim_getProcessHeaps(DWORD arg1,void * arg2) { DWORD res1; do {res1 = GetProcessHeaps(arg1, arg2); return((DWORD)(res1));} while(0); }
int _cdecl main() { struct _heapinfo info; PROCESS_HEAP_ENTRY Entry; size_t i; LPBYTE s; info._pentry = NULL; setvbuf( stdout, MyBuffer, _IOFBF, sizeof( MyBuffer ) ); _heapset( 0xAE ); while (_heapwalk( &info ) == _HEAPOK) { printf( "%08x: %05x - %s", info._pentry, info._size, info._useflag ? "busy" : "free" ); if (info._useflag == _FREEENTRY) { s = (LPBYTE)info._pentry; for (i=0; i<info._size; i++) { if (s[i] != 0xAE) { printf( " *** free block invalid at offset %x [%x]", i, s[i] ); break; } } } printf( "\n" ); fflush( stdout ); } printf( "*** end of heap ***\n\n" ); fflush( stdout ); NumberOfHeaps = GetProcessHeaps( 64, ProcessHeaps ); Entry.lpData = NULL; for (i=0; i<NumberOfHeaps; i++) { printf( "Heap[ %u ]: %x HeapCompact result: %lx\n", i, ProcessHeaps[ i ], HeapCompact( ProcessHeaps[ i ], 0 ) ); while (HeapWalk( ProcessHeaps[ i ], &Entry )) { if (Entry.wFlags & PROCESS_HEAP_REGION) { printf( " %08x: %08x - Region(First: %08x Last: %08x Committed: %x Uncommitted: %08x)\n", Entry.lpData, Entry.cbData, Entry.Region.lpFirstBlock, Entry.Region.lpLastBlock, Entry.Region.dwCommittedSize, Entry.Region.dwUnCommittedSize ); } else if (Entry.wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE) { printf( " %08x: %08x - Uncommitted\n", Entry.lpData, Entry.cbData ); } else if (Entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) { printf( " %08x: %08x - Busy", Entry.lpData, Entry.cbData ); if (Entry.wFlags & PROCESS_HEAP_ENTRY_MOVEABLE) { printf( " hMem: %08x", Entry.Block.hMem ); } if (Entry.wFlags & PROCESS_HEAP_ENTRY_DDESHARE) { printf( " DDE" ); } printf( "\n" ); } else { printf( " %08x: %08x - Free\n", Entry.lpData, Entry.cbData ); } fflush( stdout ); } printf( "*** end of heap ***\n\n" ); fflush( stdout ); } return 0; }
MX_EXPORT int mx_heap_check( unsigned long heap_flags ) { static const char fname[] = "mx_heap_check()"; DWORD number_of_heaps; DWORD maximum_number_of_heaps; HANDLE heap_handle_array[100]; HANDLE heap_handle; BOOL validate_status; int heap_ok; unsigned long i; /* This implementation does not call GetProcessHeaps() in a loop * to resize heap_handle_array to the right size, since this will * result in an infinite loop if mx_heap_check() is called from * within any of the mx_win32_... allocation functions. So we * use a fixed array instead which is probably large enough. */ static const char getprocessheaps_error[] = "ERROR: A call to GetProcessHeaps() failed.\n"; static const char toomanyheaps_error[] = "ERROR: Too many heaps reported by GetProcessHeaps(). " "Increase the size of heap_handle_array and recompile MX " "to fix this.\n"; maximum_number_of_heaps = sizeof( heap_handle_array ) / sizeof( heap_handle_array[0] ); number_of_heaps = GetProcessHeaps( maximum_number_of_heaps, heap_handle_array ); if ( number_of_heaps == 0 ) { write(2, getprocessheaps_error, sizeof(getprocessheaps_error)); } if ( number_of_heaps > maximum_number_of_heaps ) { write(2, toomanyheaps_error, sizeof(toomanyheaps_error)); return FALSE; } heap_ok = TRUE; for ( i = 0; i < number_of_heaps; i++ ) { heap_handle = heap_handle_array[i]; validate_status = HeapValidate( heap_handle, 0, 0 ); if ( validate_status == 0 ) { if ( heap_flags & MXF_HEAP_CHECK_CORRUPTED_VERBOSE ) { #if defined(_WIN64) mx_warning( "%s: Heap %lu (%#I64x) is CORRUPTED.", fname, i, (uint64_t) heap_handle ); #else mx_warning( "%s: Heap %lu (%#lx) is CORRUPTED.", fname, i, (unsigned long) heap_handle ); #endif } heap_ok = FALSE; } else { if ( heap_flags & MXF_HEAP_CHECK_OK_VERBOSE ) { #if defined(_WIN64) mx_info( "%s: Heap %lu (%#I64x) is OK.", fname, i, (uint64_t) heap_handle ); #else mx_info( "%s: Heap %lu (%#lx) is OK.", fname, i, (unsigned long) heap_handle ); #endif } } } if ( heap_ok ) { if ( heap_flags & MXF_HEAP_CHECK_OK ) { mx_info( "%s: Heap is OK", fname ); } } else { if ( heap_flags & MXF_HEAP_CHECK_CORRUPTED ) { mx_warning("%s: Heap is corrupted.", fname); } } if ( heap_flags & MXF_HEAP_CHECK_STACK_TRACEBACK ) { mx_stack_traceback(); } return heap_ok; }