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 + -
显示快捷键?