使用Xcode Instruments中的Allocations和Leaks的工具,可以帮忙开发者定位潜在的内存问题,发现不合预期的分配和泄漏。
Allocations:Analyzes the memory life-cycle of process's allocated blocks, can record reference counting events.
可以跟踪App的每一处在Heap、Anonymous VM、All VM Regions上的内存分配
Leaks:Examines a process's heap for leaked memory; use with Allocations instrument to give memory address histories.
抓取内存泄漏
环境参数配置
Build Configuration需选择非Editor的选项,如:Debug、DebugGame、Development、Test或Shipping。
Executalbe如果不修改的话,需要将ipa包后缀改成zip并解压,然后将Payload整个目录拷贝到MyTest1/Binaries/IOS中。也可以选择一个ipa包,指向包中的MyTest1.app。
定义环境变量:UE4_FORCE_MALLOC_ANSI(强制使用ansi malloc)
Profile中勾选“Use the Run action's arguments and environment variables”
(1)执行 菜单:Product -- Perform Action -- Profile Without Building
(2)拉起instruments之后,选择手机和上面的app进程,选择Allocations工具,点击“Choose”按钮来进入profiler界面
(3)点击右上角的+按钮,添加Leaks工具,点击左上角的红圈按钮,来启动进行profiler
使用Allocations跟踪内存分配
注:开了环境变量UE4_FORCE_MALLOC_ANSI后,Allocations -- Call Trees中会多一个AnsiMalloc的分类,这个分类中为UE4内存分配后没有释放的内存
注1:IOGPUResourceCreate为显卡上分配的图形资源
注2:Command + A全选,然后右键菜单“Copy Selected Frames”,将完整堆栈复制出来(含源代码文件名和代码行) -- 代码行可能会有偏差
66 libsystem_malloc.dylib 3.54 MB realloc 65 UAGame 3.54 MB AnsiRealloc(void*, unsigned long, unsigned int) [inlined] /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Private/HAL/MallocAnsi.cpp:68 64 UAGame 3.54 MB FMallocAnsi::TryRealloc(void*, unsigned long, unsigned int) [inlined] /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Private/HAL/MallocAnsi.cpp:195 63 UAGame 3.54 MB FMallocAnsi::Realloc(void*, unsigned long, unsigned int) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Private/HAL/MallocAnsi.cpp:202 62 UAGame 3.54 MB FMemory::Realloc(void*, unsigned long, unsigned int) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/HAL/FMemory.inl:0 61 UAGame 2.58 MB TSizedHeapAllocator<32>::ForAnyElementType::ResizeAllocation(int, int, unsigned long) [inlined] /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/ContainerAllocationPolicies.h:480 60 UAGame 2.58 MB TArray<TSparseArrayElementOrFreeListLink<TAlignedBytes<24, 8u> >, TSizedDefaultAllocator<32> >::ResizeGrow(int) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:2559 59 UAGame 2.34 MB TArray<TSparseArrayElementOrFreeListLink<TAlignedBytes<24, 8u> >, TSizedDefaultAllocator<32> >::AddUninitialized(int) [inlined] /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:1290 58 UAGame 2.34 MB TSparseArray<TSetElement<TTuple<UObjectBase*, int> >, TSparseArrayAllocator<TSizedDefaultAllocator<32>, FDefaultBitArrayAllocator> >::AddUninitialized() /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/SparseArray.h:129 57 UAGame 2.34 MB FSetElementId TSet<TTuple<UObjectBase*, int>, TDefaultMapHashableKeyFuncs<UObjectBase*, int, false>, FDefaultSetAllocator>::Emplace<TPairInitializer<UObjectBase*&&, int const&> >(TPairInitializer<UObjectBase*&&, int const&>&&, bool*) [inlined] /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Set.h:665 56 UAGame 2.34 MB int& TMapBase<UObjectBase*, int, FDefaultSetAllocator, TDefaultMapHashableKeyFuncs<UObjectBase*, int, false> >::Emplace<UObjectBase*, int const&>(UObjectBase*&&, int const&) [inlined] /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Map.h:404 55 UAGame 2.34 MB TMapBase<UObjectBase*, int, FDefaultSetAllocator, TDefaultMapHashableKeyFuncs<UObjectBase*, int, false> >::Add(UObjectBase*&&, int const&) [inlined] /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Map.h:364 54 UAGame 2.34 MB FLuaContext::NotifyUObjectCreated(UObjectBase const*, int) /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/UnLua/Private/LuaContext.cpp:986 53 UAGame 2.34 MB FUObjectArray::AllocateUObjectIndex(UObjectBase*, bool) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/CoreUObject/Private/UObject/UObjectArray.cpp:251 52 UAGame 2.34 MB UObjectBase::AddObject(FName, EInternalObjectFlags) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/CoreUObject/Private/UObject/UObjectBase.cpp:188 51 UAGame 2.34 MB UObjectBase::UObjectBase(UClass*, EObjectFlags, EInternalObjectFlags, UObject*, FName) [inlined] /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/CoreUObject/Private/UObject/UObjectBase.cpp:116 50 UAGame 2.34 MB UObjectBase::UObjectBase(UClass*, EObjectFlags, EInternalObjectFlags, UObject*, FName) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/CoreUObject/Private/UObject/UObjectBase.cpp:113 49 UAGame 2.34 MB StaticAllocateObject(UClass const*, UObject*, FName, EObjectFlags, EInternalObjectFlags, bool, bool*, UPackage*) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/CoreUObject/Private/UObject/UObjectGlobals.cpp:2520 48 UAGame 2.34 MB StaticConstructObject_Internal(FStaticConstructObjectParameters const&) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/CoreUObject/Private/UObject/UObjectGlobals.cpp:3210 47 UAGame 2.34 MB StaticDuplicateObjectEx(FObjectDuplicationParameters&) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/CoreUObject/Private/UObject/UObjectGlobals.cpp:2025 46 UAGame 2.34 MB AActor::CreateComponentFromTemplate(UActorComponent*, FName) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Engine/Private/ActorConstruction.cpp:1287 45 UAGame 2.34 MB USCS_Node::ExecuteNodeOnActor(AActor*, USceneComponent*, FTransform const*, FRotationConversionCache const*, bool) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Engine/Private/SCS_Node.cpp:97 44 UAGame 2.34 MB USimpleConstructionScript::ExecuteScriptOnActor(AActor*, TInlineComponentArray<USceneComponent*, 24u> const&, FTransform const&, FRotationConversionCache const*, bool) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Engine/Private/SimpleConstructionScript.cpp:689 43 UAGame 2.34 MB AActor::ExecuteConstruction(FTransform const&, FRotationConversionCache const*, FComponentInstanceDataCache const*, bool) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Engine/Private/ActorConstruction.cpp:874 42 UAGame 2.34 MB AActor::FinishSpawning(FTransform const&, bool, FComponentInstanceDataCache const*) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Engine/Private/Actor.cpp:3504 41 UAGame 2.34 MB AActor::PostSpawnInitialize(FTransform const&, AActor*, APawn*, bool, bool, bool) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Engine/Private/Actor.cpp:3424 40 UAGame 2.34 MB UWorld::SpawnActor(UClass*, FTransform const*, FActorSpawnParameters const&) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Engine/Private/LevelActor.cpp:428 39 UAGame 2.34 MB UWorld::SpawnActor(UClass*, FVector const*, FRotator const*, FActorSpawnParameters const&) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Engine/Private/LevelActor.cpp:303 38 UAGame 2.34 MB USGInventoryStatics::GetInventoryWithActorPool(UObject*, UClass*, bool, FVector const*, FRotator const*) /Users/admin/1030Version/R6Game/Plugins/SGFramework/Source/SGFramework/Private/SGGame/Inventory/SGInventoryStatics.cpp:6472 37 UAGame 2.34 MB USGCharacterAvatarManagerComponent::UpdateAvatars(TArray<TSubclassOf<ASGInventory>, TSizedDefaultAllocator<32> >, bool, TArray<long long, TSizedDefaultAllocator<32> >) /Users/admin/1030Version/R6Game/Plugins/SGFramework/Source/SGFramework/Private/SGGame/Components/Character/SGCharacterAvatarManagerComponent.cpp:237 36 UAGame 2.34 MB UUACommonStatics::UpdateAvatar(ASGCharacter*, TArray<long long, TSizedDefaultAllocator<32> >&) /Users/admin/1030Version/R6Game/Source/UACommon/Private/UACommonStatics.cpp:810 35 UAGame 2.34 MB UUACommonStatics::execUpdateAvatar(UObject*, FFrame&, void*) /Users/admin/1030Version/R6Game/Intermediate/Build/IOS/UAGame/Inc/UACommon/UACommonStatics.gen.cpp:517 34 UAGame 2.34 MB UFunction::Invoke(UObject*, FFrame&, void*) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/CoreUObject/Private/UObject/Class.cpp:5592 33 UAGame 2.34 MB FFunctionDesc::CallUE(lua_State*, int, void*) /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/UnLua/Private/ReflectionUtils/FunctionDesc.cpp:252 32 UAGame 2.34 MB luaD_precall /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/Others/Lua/src/ldo.c:500
在Leaks中查看泄漏的内存
注:Command + A全选,然后右键菜单“Copy Selected Frames”,将完整堆栈复制出来(含源代码文件名和代码行) -- 代码行可能会有偏差
0 UAGame AnsiRealloc(void*, unsigned long, unsigned int) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Private/HAL/MallocAnsi.cpp:72 1 UAGame FMallocAnsi::TryRealloc(void*, unsigned long, unsigned int) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Private/HAL/MallocAnsi.cpp:195 2 UAGame FMallocAnsi::Realloc(void*, unsigned long, unsigned int) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Private/HAL/MallocAnsi.cpp:202 3 UAGame FMemory::Realloc(void*, unsigned long, unsigned int) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/HAL/FMemory.inl:0 4 UAGame TSizedHeapAllocator<32>::ForAnyElementType::ResizeAllocation(int, int, unsigned long) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/ContainerAllocationPolicies.h:480 5 UAGame TArray<char16_t, TSizedDefaultAllocator<32> >::ResizeForCopy(int, int) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:2591 6 UAGame void TArray<char16_t, TSizedDefaultAllocator<32> >::CopyToEmpty<char16_t, int>(char16_t const*, int, int, int) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:2621 7 UAGame TArray<char16_t, TSizedDefaultAllocator<32> >::TArray(TArray<char16_t, TSizedDefaultAllocator<32> > const&) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:359 8 UAGame TArray<char16_t, TSizedDefaultAllocator<32> >::TArray(TArray<char16_t, TSizedDefaultAllocator<32> > const&) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:358 9 UAGame FString::FString(FString const&) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/UnrealString.h:83 10 UAGame FString::FString(FString const&) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/UnrealString.h:83 11 UAGame int TArray<FString, TSizedDefaultAllocator<32> >::Emplace<FString const&>(FString const&) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:1929 12 UAGame TArray<FString, TSizedDefaultAllocator<32> >::Add(FString const&) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:2002 13 UAGame void FConfigSection::MultiFind<TSizedDefaultAllocator<32> >(FName, TArray<FString, TSizedDefaultAllocator<32> >&, bool) const /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Public/Misc/ConfigCacheIni.h:240 14 UAGame FConfigFile::GetArray(char16_t const*, char16_t const*, TArray<FString, TSizedDefaultAllocator<32> >&) const /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Core/Private/Misc/ConfigCacheIni.cpp:1976 15 UAGame UUACommonConfigStatics::execGetServerIPConfig(UObject*, FFrame&, void*) /Users/admin/1030Version/R6Game/Intermediate/Build/IOS/UAGame/Inc/UACommon/UACommonConfigStatics.gen.cpp:578 16 UAGame UFunction::Invoke(UObject*, FFrame&, void*) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/CoreUObject/Private/UObject/Class.cpp:5592 17 UAGame FFunctionDesc::CallUE(lua_State*, int, void*) /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/UnLua/Private/ReflectionUtils/FunctionDesc.cpp:331 18 UAGame luaD_precall /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/Others/Lua/src/ldo.c:515 19 UAGame luaV_execute /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/Others/Lua/src/lvm.c:1134 20 UAGame luaD_call /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/Others/Lua/src/ldo.c:621 21 UAGame luaD_callnoyield /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/Others/Lua/src/ldo.c:631 22 UAGame luaD_rawrunprotected /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/Others/Lua/src/ldo.c:146 23 UAGame luaD_pcall /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/Others/Lua/src/ldo.c:851 24 UAGame lua_pcallk /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/Others/Lua/src/lapi.c:968 25 UAGame luaB_xpcall /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/Others/Lua/src/lbaselib.c:441 26 UAGame luaD_precall /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/Others/Lua/src/ldo.c:515 27 UAGame luaV_execute /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/Others/Lua/src/lvm.c:1134 28 UAGame luaD_call /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/Others/Lua/src/ldo.c:621 29 UAGame luaD_callnoyield /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/Others/Lua/src/ldo.c:631 30 UAGame luaD_rawrunprotected /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/Others/Lua/src/ldo.c:146 31 UAGame luaD_pcall /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/Others/Lua/src/ldo.c:851 32 UAGame lua_pcallk /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/Others/Lua/src/lapi.c:968 33 UAGame UnLua::FLuaRetValues UnLua::CallFunctionInternal<float&>(lua_State*, float&) /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/UnLua/Public/UnLua.inl:106 34 UAGame UnLua::FLuaRetValues UnLua::Call<float&>(lua_State*, char const*, float&) /Users/admin/1030Version/R6Game/Plugins/Tencent/UnLua/Source/UnLua/Public/UnLua.inl:656 35 UAGame UG6LuaScriptManager::Tick(float) /Users/admin/1030Version/R6Game/Plugins/Tencent/G6Framework/Source/G6Core/G6/G6LuaScriptManager.cpp:164 36 UAGame FTickableGameObject::TickObjects(UWorld*, int, bool, float) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Engine/Private/Tickable.cpp:154 37 UAGame UGameEngine::Tick(float, bool) /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Engine/Private/GameEngine.cpp:1856 38 UAGame FEngineLoop::Tick() /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/Launch/Private/LaunchEngineLoop.cpp:4836 39 UAGame -[IOSAppDelegate MainAppThread:] /Users/admin/1030Version/UnrealEngine/Engine/Source/Runtime/ApplicationCore/Private/IOS/IOSAppDelegate.cpp:506 40 Foundation __NSThread__start__ 41 libsystem_pthread.dylib _pthread_start 42 libsystem_pthread.dylib thread_start
配置可执行二进制文件和符号表文件
点击Instruments的File菜单 -- Symbols...,配置各模块的可执行二进制和dSYM符号表
点击Done,会加载一阵子,完成后,Instruments捕捉的函数地址就还原成函数名了
注:Binary和dSYM文件必须同名,否则符号会加载不成功
配置Symbols路径
注:点击菜单Instruments -- Preferences...,在面板的Symbols标签页中添加dSYM的查找路径