[UE4]追查了两天内存疯狂泄露的原因,竟然是Log没关???——UE4如何查内存泄露

各种怀疑,各种debug,最后发现是log窗口没关,因为cache机制所以内存越来越多。然后内存耗尽。。。
好吧,我比较菜。
一天后。。。[更新]
内存耗尽和log窗口的log关系不大(为了减少LOG的影响,可以在项目里面把UE_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设置断点,追查所有的新开内存,然后逐个优化掉,即可。