mmgr.cpp
来自「ftgl-2.1.2 夸平台的opengl显示字体」· C++ 代码 · 共 1,668 行 · 第 1/5 页
CPP
1,668 行
// ---------------------------------------------------------------------------------------------------------------------------------static const char *ownerString(const char *sourceFile, const unsigned int sourceLine, const char *sourceFunc){ static char str[90]; memset(str, 0, sizeof(str)); sprintf(str, "%s(%05d)::%s", sourceFileStripper(sourceFile), sourceLine, sourceFunc); return str;}// ---------------------------------------------------------------------------------------------------------------------------------static const char *insertCommas(unsigned int value){ static char str[30]; memset(str, 0, sizeof(str)); sprintf(str, "%u", value); if (strlen(str) > 3) { memmove(&str[strlen(str)-3], &str[strlen(str)-4], 4); str[strlen(str) - 4] = ','; } if (strlen(str) > 7) { memmove(&str[strlen(str)-7], &str[strlen(str)-8], 8); str[strlen(str) - 8] = ','; } if (strlen(str) > 11) { memmove(&str[strlen(str)-11], &str[strlen(str)-12], 12); str[strlen(str) - 12] = ','; } return str;}// ---------------------------------------------------------------------------------------------------------------------------------static const char *memorySizeString(unsigned long size){ static char str[90]; if (size > (1024*1024)) sprintf(str, "%10s (%7.2fM)", insertCommas(size), (float) size / (1024.0f * 1024.0f)); else if (size > 1024) sprintf(str, "%10s (%7.2fK)", insertCommas(size), (float) size / 1024.0f); else sprintf(str, "%10s bytes ", insertCommas(size)); return str;}// ---------------------------------------------------------------------------------------------------------------------------------static sAllocUnit *findAllocUnit(const void *reportedAddress){ // Just in case... m_assert(reportedAddress != NULL); // Use the address to locate the hash index. Note that we shift off the lower four bits. This is because most allocated // addresses will be on four-, eight- or even sixteen-byte boundaries. If we didn't do this, the hash index would not have // very good coverage. unsigned int hashIndex = ((unsigned int) reportedAddress >> 4) & (hashSize - 1); sAllocUnit *ptr = hashTable[hashIndex]; while(ptr) { if (ptr->reportedAddress == reportedAddress) return ptr; ptr = ptr->next; } return NULL;}// ---------------------------------------------------------------------------------------------------------------------------------static size_t calculateActualSize(const size_t reportedSize){ // We use DWORDS as our padding, and a long is guaranteed to be 4 bytes, but an int is not (ANSI defines an int as // being the standard word size for a processor; on a 32-bit machine, that's 4 bytes, but on a 64-bit machine, it's // 8 bytes, which means an int can actually be larger than a long.) return reportedSize + paddingSize * sizeof(long) * 2;}// ---------------------------------------------------------------------------------------------------------------------------------static size_t calculateReportedSize(const size_t actualSize){ // We use DWORDS as our padding, and a long is guaranteed to be 4 bytes, but an int is not (ANSI defines an int as // being the standard word size for a processor; on a 32-bit machine, that's 4 bytes, but on a 64-bit machine, it's // 8 bytes, which means an int can actually be larger than a long.) return actualSize - paddingSize * sizeof(long) * 2;}// ---------------------------------------------------------------------------------------------------------------------------------static void *calculateReportedAddress(const void *actualAddress){ // We allow this... if (!actualAddress) return NULL; // JUst account for the padding return (void *) ((char *) actualAddress + sizeof(long) * paddingSize);}// ---------------------------------------------------------------------------------------------------------------------------------static void wipeWithPattern(sAllocUnit *allocUnit, unsigned long pattern, const unsigned int originalReportedSize = 0){ // For a serious test run, we use wipes of random a random value. However, if this causes a crash, we don't want it to // crash in a differnt place each time, so we specifically DO NOT call srand. If, by chance your program calls srand(), // you may wish to disable that when running with a random wipe test. This will make any crashes more consistent so they // can be tracked down easier. if (randomWipe) { pattern = ((rand() & 0xff) << 24) | ((rand() & 0xff) << 16) | ((rand() & 0xff) << 8) | (rand() & 0xff); } // -DOC- We should wipe with 0's if we're not in debug mode, so we can help hide bugs if possible when we release the // product. So uncomment the following line for releases. // // Note that the "alwaysWipeAll" should be turned on for this to have effect, otherwise it won't do much good. But we'll // leave it this way (as an option) because this does slow things down.// pattern = 0; // This part of the operation is optional if (alwaysWipeAll && allocUnit->reportedSize > originalReportedSize) { // Fill the bulk long *lptr = (long *) ((char *)allocUnit->reportedAddress + originalReportedSize); int length = allocUnit->reportedSize - originalReportedSize; int i; for (i = 0; i < (length >> 2); i++, lptr++) { *lptr = pattern; } // Fill the remainder unsigned int shiftCount = 0; char *cptr = (char *) lptr; for (i = 0; i < (length & 0x3); i++, cptr++, shiftCount += 8) { *cptr = (pattern & (0xff << shiftCount)) >> shiftCount; } } // Write in the prefix/postfix bytes long *pre = (long *) allocUnit->actualAddress; long *post = (long *) ((char *)allocUnit->actualAddress + allocUnit->actualSize - paddingSize * sizeof(long)); for (unsigned int i = 0; i < paddingSize; i++, pre++, post++) { *pre = prefixPattern; *post = postfixPattern; }}// ---------------------------------------------------------------------------------------------------------------------------------static void dumpAllocations(FILE *fp){ fprintf(fp, "Alloc. Addr Size Addr Size BreakOn BreakOn \r\n"); fprintf(fp, "Number Reported Reported Actual Actual Unused Method Dealloc Realloc Allocated by \r\n"); fprintf(fp, "------ ---------- ---------- ---------- ---------- ---------- -------- ------- ------- --------------------------------------------------- \r\n"); for (unsigned int i = 0; i < hashSize; i++) { sAllocUnit *ptr = hashTable[i]; while(ptr) { fprintf(fp, "%06d 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X %-8s %c %c %s\r\n", ptr->allocationNumber, (unsigned int) ptr->reportedAddress, ptr->reportedSize, (unsigned int) ptr->actualAddress, ptr->actualSize, m_calcUnused(ptr), allocationTypes[ptr->allocationType], ptr->breakOnDealloc ? 'Y':'N', ptr->breakOnRealloc ? 'Y':'N', ownerString(ptr->sourceFile, ptr->sourceLine, ptr->sourceFunc)); ptr = ptr->next; } }}// ---------------------------------------------------------------------------------------------------------------------------------static void dumpLeakReport(){ // Open the report file FILE *fp = fopen(memoryLeakLogFile, "w+b"); // If you hit this assert, then the memory report generator is unable to log information to a file (can't open the file for // some reason.) m_assert(fp); if (!fp) return; // Any leaks? // Header static char timeString[25]; memset(timeString, 0, sizeof(timeString)); time_t t = time(NULL); struct tm *tme = localtime(&t); fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n"); fprintf(fp, "| Memory leak report for: %02d/%02d/%04d %02d:%02d:%02d |\r\n", tme->tm_mon + 1, tme->tm_mday, tme->tm_year + 1900, tme->tm_hour, tme->tm_min, tme->tm_sec); fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n"); fprintf(fp, "\r\n"); fprintf(fp, "\r\n"); if (stats.totalAllocUnitCount) { fprintf(fp, "%d memory leak%s found:\r\n", stats.totalAllocUnitCount, stats.totalAllocUnitCount == 1 ? "":"s"); } else { fprintf(fp, "Congratulations! No memory leaks found!\r\n"); // We can finally free up our own memory allocations if (reservoirBuffer) { for (unsigned int i = 0; i < reservoirBufferSize; i++) { free(reservoirBuffer[i]); } free(reservoirBuffer); reservoirBuffer = 0; reservoirBufferSize = 0; reservoir = NULL; } } fprintf(fp, "\r\n"); if (stats.totalAllocUnitCount) { dumpAllocations(fp); } fclose(fp);}// ---------------------------------------------------------------------------------------------------------------------------------// We use a static class to let us know when we're in the midst of static deinitialization// ---------------------------------------------------------------------------------------------------------------------------------class MemStaticTimeTracker{public: MemStaticTimeTracker() {doCleanupLogOnFirstRun();} ~MemStaticTimeTracker() {staticDeinitTime = true; dumpLeakReport();}};static MemStaticTimeTracker mstt;// ---------------------------------------------------------------------------------------------------------------------------------// -DOC- Flags & options -- Call these routines to enable/disable the following options// ---------------------------------------------------------------------------------------------------------------------------------bool &m_alwaysValidateAll(){ // Force a validation of all allocation units each time we enter this software return alwaysValidateAll;}// ---------------------------------------------------------------------------------------------------------------------------------bool &m_alwaysLogAll(){ // Force a log of every allocation & deallocation into memory.log return alwaysLogAll;}// ---------------------------------------------------------------------------------------------------------------------------------bool &m_alwaysWipeAll(){ // Force this software to always wipe memory with a pattern when it is being allocated/dallocated return alwaysWipeAll;}// ---------------------------------------------------------------------------------------------------------------------------------bool &m_randomeWipe(){ // Force this software to use a random pattern when wiping memory -- good for stress testing return randomWipe;}// ---------------------------------------------------------------------------------------------------------------------------------// -DOC- Simply call this routine with the address of an allocated block of RAM, to cause it to force a breakpoint when it is// reallocated.// ---------------------------------------------------------------------------------------------------------------------------------bool &m_breakOnRealloc(void *reportedAddress){ // Locate the existing allocation unit sAllocUnit *au = findAllocUnit(reportedAddress); // If you hit this assert, you tried to set a breakpoint on reallocation for an address that doesn't exist. Interrogate the // stack frame or the variable 'au' to see which allocation this is. m_assert(au != NULL); // If you hit this assert, you tried to set a breakpoint on reallocation for an address that wasn't allocated in a way that // is compatible with reallocation. m_assert(au->allocationType == m_alloc_malloc || au->allocationType == m_alloc_calloc || au->allocationType == m_alloc_realloc); return au->breakOnRealloc;}// ---------------------------------------------------------------------------------------------------------------------------------// -DOC- Simply call this routine with the address of an allocated block of RAM, to cause it to force a breakpoint when it is// deallocated.// ---------------------------------------------------------------------------------------------------------------------------------bool &m_breakOnDealloc(void *reportedAddress){ // Locate the existing allocation unit sAllocUnit *au = findAllocUnit(reportedAddress); // If you hit this assert, you tried to set a breakpoint on deallocation for an address that doesn't exist. Interrogate the // stack frame or the variable 'au' to see which allocation this is. m_assert(au != NULL); return au->breakOnDealloc;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?