[UE4]追查了两天内存疯狂泄露的原因,竟然是Log没关???——UE4如何查内存泄露
发布时间:2022年7月25日 03:20:29 作者:追梦
文本颜色
背景颜色
插入画图
xxxxxxxxxx
各种怀疑,各种debug,最后发现是log窗口没关,因为cache机制所以内存越来越多。然后内存耗尽。。。
好吧,我比较菜。
一天后。。。[更新]
内存耗尽和log窗口的log关系不大,主要是ue4下使用std标准库,因为不同的内存管理机制,会造成内存被cache住无法释放。
在UE4引擎端,会hook所有的内存分配。
`Engine\Source\Runtime\Core\Public\HAL\FMemory.inl`
```c++
FMEMORY_INLINE_FUNCTION_DECORATOR void* FMemory::Malloc(SIZE_T Count, uint32 Alignment)
{
void* Ptr;
if (!FMEMORY_INLINE_GMalloc)
{
Ptr = MallocExternal(Count, Alignment);
}
else
{
DoGamethreadHook(0);
FScopedMallocTimer Timer(0);
Ptr = FMEMORY_INLINE_GMalloc->Malloc(Count, Alignment);
}
// optional tracking of every allocation
LLM_IF_ENABLED(FLowLevelMemTracker::Get().OnLowLevelAlloc(ELLMTracker::Default, Ptr, Count, ELLMTag::Untagged, ELLMAllocType::FMalloc));
return Ptr;
}
FMEMORY_INLINE_FUNCTION_DECORATOR void* FMemory::Realloc(void* Original, SIZE_T Count, uint32 Alignment)
{
// optional tracking -- a realloc with an Original pointer of null is equivalent
// to malloc() so there's nothing to free
LLM_REALLOC_SCOPE(Original);
LLM_IF_ENABLED(if (Original != nullptr) FLowLevelMemTracker::Get().OnLowLevelFree(ELLMTracker::Default, Original, ELLMAllocType::FMalloc));
void* Ptr;
if (!FMEMORY_INLINE_GMalloc)
{
Ptr = ReallocExternal(Original, Count, Alignment);
}
else
{
DoGamethreadHook(1);
FScopedMallocTimer Timer(1);
Ptr = FMEMORY_INLINE_GMalloc->Realloc(Original, Count, Alignment);
}
// optional tracking of every allocation - a realloc with a Count of zero is equivalent to a call
// to free() and will return a null pointer which does not require tracking. If realloc returns null
// for some other reason (like failure to allocate) there's also no reason to track it
LLM_IF_ENABLED(if (Ptr != nullptr) FLowLevelMemTracker::Get().OnLowLevelAlloc(ELLMTracker::Default, Ptr, Count, ELLMTag::Untagged, ELLMAllocType::FMalloc));
return Ptr;
}
FMEMORY_INLINE_FUNCTION_DECORATOR void FMemory::Free(void* Original)
{
if (!Original)
{
FScopedMallocTimer Timer(3);
return;
}
// optional tracking of every allocation
LLM_IF_ENABLED(FLowLevelMemTracker::Get().OnLowLevelFree(ELLMTracker::Default, Original, ELLMAllocType::FMalloc));
if (!FMEMORY_INLINE_GMalloc)
{
FreeExternal(Original);
return;
}
DoGamethreadHook(2);
FScopedMallocTimer Timer(2);
FMEMORY_INLINE_GMalloc->Free(Original);
}
```
所有的内存分配如果是新增内存,走 FMemory::Malloc,如果是已有内存走 FMemory::Realloc。std有自己的一套内存管理机制。会造成内存无法被ue4立即释放。
所以最后是用TArray,TMap,TSet等Ue4容器代替std容器。
然后在FMomory::Malloc和Memory::Realloc设置断点,追查所有的新开内存,然后逐个优化掉,即可。
各种怀疑,各种debug,最后发现是log窗口没关,因为cache机制所以内存越来越多。然后内存耗尽。。。
好吧,我比较菜。
一天后。。。[更新]
内存耗尽和log窗口的log关系不大,主要是ue4下使用std标准库,因为不同的内存管理机制,会造成内存被cache住无法释放。
在UE4引擎端,会hook所有的内存分配。Engine\Source\Runtime\Core\Public\HAL\FMemory.inl
FMEMORY_INLINE_FUNCTION_DECORATOR void* FMemory::Malloc(SIZE_T Count, uint32 Alignment)
{
void* Ptr;
if (!FMEMORY_INLINE_GMalloc)
{
Ptr = MallocExternal(Count, Alignment);
}
else
{
DoGamethreadHook(0);
FScopedMallocTimer Timer(0);
Ptr = FMEMORY_INLINE_GMalloc->Malloc(Count, Alignment);
}
// optional tracking of every allocation
LLM_IF_ENABLED(FLowLevelMemTracker::Get().OnLowLevelAlloc(ELLMTracker::Default, Ptr, Count, ELLMTag::Untagged, ELLMAllocType::FMalloc));
return Ptr;
}
FMEMORY_INLINE_FUNCTION_DECORATOR void* FMemory::Realloc(void* Original, SIZE_T Count, uint32 Alignment)
{
// optional tracking -- a realloc with an Original pointer of null is equivalent
// to malloc() so there's nothing to free
LLM_REALLOC_SCOPE(Original);
LLM_IF_ENABLED(if (Original != nullptr) FLowLevelMemTracker::Get().OnLowLevelFree(ELLMTracker::Default, Original, ELLMAllocType::FMalloc));
void* Ptr;
if (!FMEMORY_INLINE_GMalloc)
{
Ptr = ReallocExternal(Original, Count, Alignment);
}
else
{
DoGamethreadHook(1);
FScopedMallocTimer Timer(1);
Ptr = FMEMORY_INLINE_GMalloc->Realloc(Original, Count, Alignment);
}
// optional tracking of every allocation - a realloc with a Count of zero is equivalent to a call
// to free() and will return a null pointer which does not require tracking. If realloc returns null
// for some other reason (like failure to allocate) there's also no reason to track it
LLM_IF_ENABLED(if (Ptr != nullptr) FLowLevelMemTracker::Get().OnLowLevelAlloc(ELLMTracker::Default, Ptr, Count, ELLMTag::Untagged, ELLMAllocType::FMalloc));
return Ptr;
}
FMEMORY_INLINE_FUNCTION_DECORATOR void FMemory::Free(void* Original)
{
if (!Original)
{
FScopedMallocTimer Timer(3);
return;
}
// optional tracking of every allocation
LLM_IF_ENABLED(FLowLevelMemTracker::Get().OnLowLevelFree(ELLMTracker::Default, Original, ELLMAllocType::FMalloc));
if (!FMEMORY_INLINE_GMalloc)
{
FreeExternal(Original);
return;
}
DoGamethreadHook(2);
FScopedMallocTimer Timer(2);
FMEMORY_INLINE_GMalloc->Free(Original);
}
所有的内存分配如果是新增内存,走 FMemory::Malloc,如果是已有内存走 FMemory::Realloc。std有自己的一套内存管理机制。会造成内存无法被ue4立即释放。
所以最后是用TArray,TMap,TSet等Ue4容器代替std容器。
然后在FMomory::Malloc和Memory::Realloc设置断点,追查所有的新开内存,然后逐个优化掉,即可。
文本颜色
背景颜色
标签:
ue4
Villanueva
5 months 7 days ago
Reply to: rE_lVEm5
Delete
Hannon
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Cunningham
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Burdine
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Hasan
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Reel
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Pulido
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Perry
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Casas
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Hatton
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Bouchard
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Stinson
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Rawls
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Castellano
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Popp
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Norman
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Kimball
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Bostick
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Bullen
1 years 8 months ago
Reply to: rE_lVEm5
Delete
Van
1 years 8 months ago
Reply to: rE_lVEm5
Delete