void FMemory::Free( void* Original ) { if( !GMalloc ) { GCreateMalloc(); CA_ASSUME( GMalloc != NULL ); // Don't want to assert, but suppress static analysis warnings about potentially NULL GMalloc } return GMalloc->Free( Original ); }
void* FMemory::Realloc( void* Original, SIZE_T Count, uint32 Alignment ) { if( !GMalloc ) { GCreateMalloc(); CA_ASSUME( GMalloc != NULL ); // Don't want to assert, but suppress static analysis warnings about potentially NULL GMalloc } return GMalloc->Realloc( Original, Count, Alignment ); }
/** * Captures the current stack and updates stack tracking information. * optionally stores a user data pointer that the tracker will take ownership of and delete upon reset * you must allocate the memory with FMemory::Malloc() */ void FStackTracker::CaptureStackTrace(int32 EntriesToIgnore /*=2*/, void* UserData /*=NULL*/) { // Avoid re-rentrancy as the code uses TArray/TMap. if( !bAvoidCapturing && bIsEnabled ) { // Scoped true/ false. bAvoidCapturing = true; // Capture callstack and create CRC. uint64* FullBackTrace = NULL; FullBackTrace = static_cast<uint64*>(FMemory_Alloca((MAX_BACKTRACE_DEPTH + EntriesToIgnore) * sizeof(uint64))); FPlatformStackWalk::CaptureStackBackTrace( FullBackTrace, MAX_BACKTRACE_DEPTH + EntriesToIgnore ); CA_ASSUME(FullBackTrace); // Skip first NUM_ENTRIES_TO_SKIP entries as they are inside this code uint64* BackTrace = &FullBackTrace[EntriesToIgnore]; uint32 CRC = FCrc::MemCrc_DEPRECATED( BackTrace, MAX_BACKTRACE_DEPTH * sizeof(uint64) ); // Use index if found int32* IndexPtr = CRCToCallStackIndexMap.Find( CRC ); if( IndexPtr ) { // Increase stack count for existing callstack. CallStacks[*IndexPtr].StackCount++; if (UpdateFn) { UpdateFn(CallStacks[*IndexPtr], UserData); } //We can delete this since the user gives ownership at the beginning of this call //and had a chance to update their data inside the above callback if (UserData) { FMemory::Free(UserData); } } // Encountered new call stack, add to array and set index mapping. else { // Add to array and set mapping for future use. int32 Index = CallStacks.AddUninitialized(); CRCToCallStackIndexMap.Add( CRC, Index ); // Fill in callstack and count. FCallStack& CallStack = CallStacks[Index]; FMemory::Memcpy( CallStack.Addresses, BackTrace, sizeof(uint64) * MAX_BACKTRACE_DEPTH ); CallStack.StackCount = 1; CallStack.UserData = UserData; } // We're done capturing. bAvoidCapturing = false; } }
class ITargetPlatformManagerModule& GetTargetPlatformManagerRef() { class ITargetPlatformManagerModule* SingletonInterface = GetTargetPlatformManager(); if (!SingletonInterface) { UE_LOG(LogInit, Fatal, TEXT("Target platform manager was requested, but not available.")); CA_ASSUME( SingletonInterface != NULL ); // Suppress static analysis warning in unreachable code (fatal error) } return *SingletonInterface; }
class FDerivedDataCacheInterface& GetDerivedDataCacheRef() { class FDerivedDataCacheInterface* SingletonInterface = GetDerivedDataCache(); if (!SingletonInterface) { UE_LOG(LogInit, Fatal, TEXT("Derived Data Cache was requested, but not available.")); CA_ASSUME( SingletonInterface != NULL ); // Suppress static analysis warning in unreachable code (fatal error) } return *SingletonInterface; }
SIZE_T FMemory::GetAllocSize( void* Original ) { if( !GMalloc ) { GCreateMalloc(); CA_ASSUME( GMalloc != NULL ); // Don't want to assert, but suppress static analysis warnings about potentially NULL GMalloc } SIZE_T Size = 0; return GMalloc->GetAllocationSize( Original, Size ) ? Size : 0; }
void FMemory::TestMemory() { #if !UE_BUILD_SHIPPING if( !GMalloc ) { GCreateMalloc(); CA_ASSUME( GMalloc != NULL ); // Don't want to assert, but suppress static analysis warnings about potentially NULL GMalloc } // track the pointers to free next call to the function static TArray<void*> LeakedPointers; TArray<void*> SavedLeakedPointers = LeakedPointers; // note that at the worst case, there will be NumFreedAllocations + 2 * NumLeakedAllocations allocations alive static const int NumFreedAllocations = 1000; static const int NumLeakedAllocations = 100; static const int MaxAllocationSize = 128 * 1024; TArray<void*> FreedPointers; // allocate pointers that will be freed later for (int32 Index = 0; Index < NumFreedAllocations; Index++) { FreedPointers.Add(FMemory::Malloc(FMath::RandHelper(MaxAllocationSize))); } // allocate pointers that will be leaked until the next call LeakedPointers.Empty(); for (int32 Index = 0; Index < NumLeakedAllocations; Index++) { LeakedPointers.Add(FMemory::Malloc(FMath::RandHelper(MaxAllocationSize))); } // free the leaked pointers from _last_ call to this function for (int32 Index = 0; Index < SavedLeakedPointers.Num(); Index++) { FMemory::Free(SavedLeakedPointers[Index]); } // free the non-leaked pointers from this call to this function for (int32 Index = 0; Index < FreedPointers.Num(); Index++) { FMemory::Free(FreedPointers[Index]); } #endif }
/** * Captures the current stack and updates stack tracking information. * optionally stores a user data pointer that the tracker will take ownership of and delete upon reset * you must allocate the memory with FMemory::Malloc() */ void FStackTracker::CaptureStackTrace(int32 EntriesToIgnore, void* UserData, int32 StackLen, bool bLookupStringsForAliasRemoval) { // Avoid re-rentrancy as the code uses TArray/TMap. if( !bAvoidCapturing && bIsEnabled ) { // Scoped true/ false. bAvoidCapturing = true; // Capture callstack and create CRC. int32 Size = (MAX_BACKTRACE_DEPTH + EntriesToIgnore) * sizeof(uint64); uint64* FullBackTrace = static_cast<uint64*>(FMemory_Alloca(Size)); FMemory::Memzero(FullBackTrace, Size); FPlatformStackWalk::CaptureStackBackTrace( FullBackTrace, MAX_BACKTRACE_DEPTH + EntriesToIgnore ); CA_ASSUME(FullBackTrace); // Skip first NUM_ENTRIES_TO_SKIP entries as they are inside this code uint64* BackTrace = &FullBackTrace[EntriesToIgnore]; if (StackLen < MAX_BACKTRACE_DEPTH) { FMemory::Memzero(BackTrace + StackLen, sizeof(uint64) * (MAX_BACKTRACE_DEPTH - StackLen)); } if (bLookupStringsForAliasRemoval) { for (int32 Index = 0; Index < StackLen; Index++) { if (BackTrace[Index]) { uint64* Existing = AliasMap.Find(BackTrace[Index]); if (Existing) { BackTrace[Index] = *Existing; } else { ANSICHAR AddressInformation[512]; AddressInformation[0] = 0; FPlatformStackWalk::ProgramCounterToHumanReadableString( 1, BackTrace[Index], AddressInformation, ARRAY_COUNT(AddressInformation)-1 ); FString Symbol(AddressInformation); int32 Spot = Symbol.Find(TEXT(" - ")); if (Spot != INDEX_NONE) { Symbol = Symbol.RightChop(Spot + 3); } Existing = StringAliasMap.Find(Symbol); if (Existing) { AliasMap.Add(BackTrace[Index], *Existing); BackTrace[Index] = *Existing; } else { AliasMap.Add(BackTrace[Index], BackTrace[Index]); StringAliasMap.Add(Symbol, BackTrace[Index]); } } } } } uint32 CRC = FCrc::MemCrc_DEPRECATED( BackTrace, MAX_BACKTRACE_DEPTH * sizeof(uint64) ); // Use index if found int32* IndexPtr = CRCToCallStackIndexMap.Find( CRC ); if( IndexPtr ) { // Increase stack count for existing callstack. CallStacks[*IndexPtr].StackCount++; if (UpdateFn) { UpdateFn(CallStacks[*IndexPtr], UserData); } //We can delete this since the user gives ownership at the beginning of this call //and had a chance to update their data inside the above callback if (UserData) { FMemory::Free(UserData); } } // Encountered new call stack, add to array and set index mapping. else { // Add to array and set mapping for future use. int32 Index = CallStacks.AddUninitialized(); CRCToCallStackIndexMap.Add( CRC, Index ); // Fill in callstack and count. FCallStack& CallStack = CallStacks[Index]; FMemory::Memcpy( CallStack.Addresses, BackTrace, sizeof(uint64) * MAX_BACKTRACE_DEPTH ); CallStack.StackCount = 1; CallStack.UserData = UserData; } // We're done capturing. bAvoidCapturing = false; } }