mmgr.cpp
来自「ftgl-2.1.2 夸平台的opengl显示字体」· C++ 代码 · 共 1,668 行 · 第 1/5 页
CPP
1,668 行
log("[D] EXIT : delete"); #endif}// ---------------------------------------------------------------------------------------------------------------------------------void operator delete[](void *reportedAddress){ #ifdef TEST_MEMORY_MANAGER log("[D] ENTER: delete[]"); #endif // ANSI says: delete & delete[] allow NULL pointers (they do nothing) if (reportedAddress) m_deallocator(sourceFile, sourceLine, sourceFunc, m_alloc_delete_array, reportedAddress); else if (alwaysLogAll) log("[-] ----- %8s of NULL by %s", allocationTypes[m_alloc_delete_array], ownerString(sourceFile, sourceLine, sourceFunc)); // Resetting the globals insures that if at some later time, somebody calls our memory manager from an unknown // source (i.e. they didn't include our H file) then we won't think it was the last allocation. resetGlobals(); #ifdef TEST_MEMORY_MANAGER log("[D] EXIT : delete[]"); #endif}// ---------------------------------------------------------------------------------------------------------------------------------// Allocate memory and track it// ---------------------------------------------------------------------------------------------------------------------------------void *m_allocator(const char *sourceFile, const unsigned int sourceLine, const char *sourceFunc, const unsigned int allocationType, const size_t reportedSize){ try { #ifdef TEST_MEMORY_MANAGER log("[D] ENTER: m_allocator()"); #endif // Increase our allocation count currentAllocationCount++; // Log the request if (alwaysLogAll) log("[+] %05d %8s of size 0x%08X(%08d) by %s", currentAllocationCount, allocationTypes[allocationType], reportedSize, reportedSize, ownerString(sourceFile, sourceLine, sourceFunc)); // If you hit this assert, you requested a breakpoint on a specific allocation count m_assert(currentAllocationCount != breakOnAllocationCount); // If necessary, grow the reservoir of unused allocation units if (!reservoir) { // Allocate 256 reservoir elements reservoir = (sAllocUnit *) malloc(sizeof(sAllocUnit) * 256); // If you hit this assert, then the memory manager failed to allocate internal memory for tracking the // allocations m_assert(reservoir != NULL); // Danger Will Robinson! if (reservoir == NULL) throw "Unable to allocate RAM for internal memory tracking data"; // Build a linked-list of the elements in our reservoir memset(reservoir, 0, sizeof(sAllocUnit) * 256); for (unsigned int i = 0; i < 256 - 1; i++) { reservoir[i].next = &reservoir[i+1]; } // Add this address to our reservoirBuffer so we can free it later sAllocUnit **temp = (sAllocUnit **) realloc(reservoirBuffer, (reservoirBufferSize + 1) * sizeof(sAllocUnit *)); m_assert(temp); if (temp) { reservoirBuffer = temp; reservoirBuffer[reservoirBufferSize++] = reservoir; } } // Logical flow says this should never happen... m_assert(reservoir != NULL); // Grab a new allocaton unit from the front of the reservoir sAllocUnit *au = reservoir; reservoir = au->next; // Populate it with some real data memset(au, 0, sizeof(sAllocUnit)); au->actualSize = calculateActualSize(reportedSize); #ifdef RANDOM_FAILURE double a = rand(); double b = RAND_MAX / 100.0 * RANDOM_FAILURE; if (a > b) { au->actualAddress = malloc(au->actualSize); } else { log("[F] Random faiure"); au->actualAddress = NULL; } #else au->actualAddress = malloc(au->actualSize); #endif au->reportedSize = reportedSize; au->reportedAddress = calculateReportedAddress(au->actualAddress); au->allocationType = allocationType; au->sourceLine = sourceLine; au->allocationNumber = currentAllocationCount; if (sourceFile) strncpy(au->sourceFile, sourceFileStripper(sourceFile), sizeof(au->sourceFile) - 1); else strcpy (au->sourceFile, "??"); if (sourceFunc) strncpy(au->sourceFunc, sourceFunc, sizeof(au->sourceFunc) - 1); else strcpy (au->sourceFunc, "??"); // We don't want to assert with random failures, because we want the application to deal with them. #ifndef RANDOM_FAILURE // If you hit this assert, then the requested allocation simply failed (you're out of memory.) Interrogate the // variable 'au' or the stack frame to see what you were trying to do. m_assert(au->actualAddress != NULL); #endif if (au->actualAddress == NULL) { throw "Request for allocation failed. Out of memory."; } // If you hit this assert, then this allocation was made from a source that isn't setup to use this memory tracking // software, use the stack frame to locate the source and include our H file. m_assert(allocationType != m_alloc_unknown); // Insert the new allocation into the hash table unsigned int hashIndex = ((unsigned int) au->reportedAddress >> 4) & (hashSize - 1); if (hashTable[hashIndex]) hashTable[hashIndex]->prev = au; au->next = hashTable[hashIndex]; au->prev = NULL; hashTable[hashIndex] = au; // Account for the new allocatin unit in our stats stats.totalReportedMemory += au->reportedSize; stats.totalActualMemory += au->actualSize; stats.totalAllocUnitCount++; if (stats.totalReportedMemory > stats.peakReportedMemory) stats.peakReportedMemory = stats.totalReportedMemory; if (stats.totalActualMemory > stats.peakActualMemory) stats.peakActualMemory = stats.totalActualMemory; if (stats.totalAllocUnitCount > stats.peakAllocUnitCount) stats.peakAllocUnitCount = stats.totalAllocUnitCount; stats.accumulatedReportedMemory += au->reportedSize; stats.accumulatedActualMemory += au->actualSize; stats.accumulatedAllocUnitCount++; // Prepare the allocation unit for use (wipe it with recognizable garbage) wipeWithPattern(au, unusedPattern); // calloc() expects the reported memory address range to be filled with 0's if (allocationType == m_alloc_calloc) { memset(au->reportedAddress, 0, au->reportedSize); } // Validate every single allocated unit in memory if (alwaysValidateAll) m_validateAllAllocUnits(); // Log the result if (alwaysLogAll) log("[+] ----> addr 0x%08X", (unsigned int) au->reportedAddress); // Resetting the globals insures that if at some later time, somebody calls our memory manager from an unknown // source (i.e. they didn't include our H file) then we won't think it was the last allocation. resetGlobals(); // Return the (reported) address of the new allocation unit #ifdef TEST_MEMORY_MANAGER log("[D] EXIT : m_allocator()"); #endif return au->reportedAddress; } catch(const char *err) { // Deal with the errors log("[!] %s", err); resetGlobals(); #ifdef TEST_MEMORY_MANAGER log("[D] EXIT : m_allocator()"); #endif return NULL; }}// ---------------------------------------------------------------------------------------------------------------------------------// Reallocate memory and track it// ---------------------------------------------------------------------------------------------------------------------------------void *m_reallocator(const char *sourceFile, const unsigned int sourceLine, const char *sourceFunc, const unsigned int reallocationType, const size_t reportedSize, void *reportedAddress){ try { #ifdef TEST_MEMORY_MANAGER log("[D] ENTER: m_reallocator()"); #endif // Calling realloc with a NULL should force same operations as a malloc if (!reportedAddress) { return m_allocator(sourceFile, sourceLine, sourceFunc, reallocationType, reportedSize); } // Increase our allocation count currentAllocationCount++; // If you hit this assert, you requested a breakpoint on a specific allocation count m_assert(currentAllocationCount != breakOnAllocationCount); // Log the request if (alwaysLogAll) log("[~] %05d %8s of size 0x%08X(%08d) by %s", currentAllocationCount, allocationTypes[reallocationType], reportedSize, reportedSize, ownerString(sourceFile, sourceLine, sourceFunc)); // Locate the existing allocation unit sAllocUnit *au = findAllocUnit(reportedAddress); // If you hit this assert, you tried to reallocate RAM that wasn't allocated by this memory manager. m_assert(au != NULL); if (au == NULL) throw "Request to reallocate RAM that was never allocated"; // If you hit this assert, then the allocation unit that is about to be reallocated is damaged. But you probably // already know that from a previous assert you should have seen in validateAllocUnit() :) m_assert(m_validateAllocUnit(au)); // If you hit this assert, then this reallocation was made from a source that isn't setup to use this memory // tracking software, use the stack frame to locate the source and include our H file. m_assert(reallocationType != m_alloc_unknown); // If you hit this assert, you were trying to reallocate RAM that was not allocated in a way that is compatible with // realloc. In other words, you have a allocation/reallocation mismatch. m_assert(au->allocationType == m_alloc_malloc || au->allocationType == m_alloc_calloc || au->allocationType == m_alloc_realloc); // If you hit this assert, then the "break on realloc" flag for this allocation unit is set (and will continue to be // set until you specifically shut it off. Interrogate the 'au' variable to determine information about this // allocation unit. m_assert(au->breakOnRealloc == false); // Keep track of the original size unsigned int originalReportedSize = au->reportedSize; if (alwaysLogAll) log("[~] ----> from 0x%08X(%08d)", originalReportedSize, originalReportedSize); // Do the reallocation void *oldReportedAddress = reportedAddress; size_t newActualSize = calculateActualSize(reportedSize); void *newActualAddress = NULL; #ifdef RANDOM_FAILURE double a = rand(); double b = RAND_MAX / 100.0 * RANDOM_FAILURE; if (a > b) { newActualAddress = realloc(au->actualAddress, newActualSize); } else { log("[F] Random faiure"); } #else newActualAddress = realloc(au->actualAddress, newActualSize); #endif // We don't want to assert with random failures, because we want the application to deal with them. #ifndef RANDOM_FAILURE // If you hit this assert, then the requested allocation simply failed (you're out of memory) Interrogate the // variable 'au' to see the original allocation. You can also query 'newActualSize' to see the amount of memory // trying to be allocated. Finally, you can query 'reportedSize' to see how much memory was requested by the caller. m_assert(newActualAddress); #endif if (!newActualAddress) throw "Request for reallocation failed. Out of memory."; // Remove this allocation from our stats (we'll add the new reallocation again later) stats.totalReportedMemory -= au->reportedSize; stats.totalActualMemory -= au->actualSize; // Update the allocation with the new information au->actualSize = newActualSize; au->actualAddress = newActualAddress; au->reportedSize = calculateReportedSize(newActualSize); au->reportedAddress = calculateReportedAddress(newActualAddress); au->allocationType = reallocationType; au->sourceLine = sourceLine; au->allocationNumber = currentAllocationCount; if (sourceFile) strncpy(au->sourceFile, sourceFileStripper(sourceFile), sizeof(au->sourceFile) - 1); else strcpy (au->sourceFile, "??"); if (sourceFunc) strncpy(au->sourceFunc, sourceFunc, sizeof(au->sourceFunc) - 1); else strcpy (au->sourceFunc, "??"); // The reallocation may cause the address to change, so we should relocate our allocation unit within the hash table unsigned int hashIndex = (unsigned int) -1; if (oldReportedAddress != au->reportedAddress) { // Remove this allocation unit from the hash table { unsigned int hashIndex = ((unsigned int) oldReportedAddress >> 4) & (hashSize - 1); if (hashTable[hashIndex] == au) { hashTable[hashIndex] = hashTable[hashIndex]->next; } else
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?