简介: 系统浏览第一站,GC,本文先梳理一个GC系统的浏览路径,基本分成5个核心阶段,并在文末提供了调试技巧与
📁 核心代码文件清单
Engine/Source/Runtime/CoreUObject/Public/UObject/
├── GarbageCollection.h # GC策略定义
├── ObjectMacros.h # `GENERATED_BODY()`的GC宏
└── UObjectBase.h # `UObject`生命周期函数
Engine/Source/Runtime/CoreUObject/Private/UObject/
├── GarbageCollection.cpp # GC主逻辑 (90%代码)
├── UObjectGarbageCollection.cpp # 对象级回收实现
└── AsyncPurge.cpp # 异步清理线程
Engine/Source/Runtime/CoreUObject/Private/Serialization/
└── ObjectWriter.cpp # GC与序列化交互 (`FReferenceCollector`)
阶段1:GC核心机制与标记流程
-
模块入口
- 模块:CoreUObject
- 启动入口:声明在 UObjectGlobals.h→ CollectGarbage() ,定义在GarbageCollection.cpp->CollectGarbage(EObjectFlags KeepFlags, bool bPerformFullPurge)
- 内部调用函数:UE::GC::CollectGarbageInternal(KeepFlags, bPerformFullPurge);
-
标记阶段(Marking)
- 关键类:
- FReachabilityAnalysisState::PerformReachabilityAnalysis()
- FRealtimeGC → PerformReachabilityAnalysis()
- 关键函数:
- PerformReachabilityAnalysis(...) (可达性分析)
- StartVerseGC() (UE 新推出的 Verse 编程语言,这里是做了对它的 GC 标记功能的支持)
- StartReachabilityAnalysis(...)(开始分析)
- BeginInitialReferenceCollection(...)(判断是否并行处理)
- MarkObjectsAsUnreachable(...)(标记不可达到的标签)
- FGCFlags::SwapReachableAndMaybeUnreachable()(翻转标记为)
- MarkClusteredObjectsAsReachable(...)(按簇标记可达性)
- MarkRootObjectAsReachable(...)(标记根节点的可达性)
- PerformReachabilityAnalysis(...) (可达性分析)
- 关键类:
-
文件路径:
- Engine/Source/Runtime/CoreUObject/Public/UObject/GarbageCollection.h
- Engine/Source/Runtime/CoreUObject/Private/UObject/GarbageCollection.cpp
- Engine/Source/Runtime/CoreUObject/Public/UObject/UObjectArray.h
阶段2:内存回收与销毁流程
-
回收阶段(Sweeping)
- 关键函数:
- void FReachabilityAnalysisState::PerformReachabilityAnalysisAndConditionallyPurgeGarbage(bool bReachabilityUsingTimeLimit) 分析并回收的入口
- UE::GC::PostCollectGarbageImpl<true>(ObjectKeepFlags); 真正回收操作的调用
- UE::GC::GatherUnreachableObjects 搜集所有不可达对象
- UnhashUnreachableObjects 解除对象的 hash 关联
- IncrementalPurgeGarbage 实际的清理调用
- IncrementalDestroyGarbage 销毁 Garbage (在 IncrementalPurgeGarbage 内部调用)
- Object->ConditionalFinishDestroy(); 在 IncrementalDestroyGarbage 内部调用 UObject 的销毁函数,实现Object 的真正销毁
- GUObjectPurge.DestroyObjects(bUseTimeLimit, TimeLimit, GCStartTime); 提供流程控制和系统管理
- IncrementalDestroyGarbage 销毁 Garbage (在 IncrementalPurgeGarbage 内部调用)
- 关键函数:
🔧 关键调试技巧
-
触发GC断点调试
- 控制台命令:
ForceGarbageCollection // 强制触发完整GC Obj List -unreachable // 打印不可达对象- 断点位置:
- CollectGarbage()(回收入口)
- IsValid(Object)(检测悬垂指针)
-
检测内存泄漏
- 日志过滤:
LogGarbage: Log // 打印GC过程对象数 LogUObjectHash: Log // 跟踪对象哈希表- 工具:
- 内存分析器:UnrealInsights → "Garbage Collection"轨道
- 常见崩溃场景分析
| 错误现象 | 根源代码 | 解决方法 |
|---|---|---|
| “Attempted to access garbage!” | UObject::IsValid() 失败 | 检查弱引用升级UObject* |
| “Already in pending kill” | UObject::ConditionalBeginDestroy()被重复调用 | 清除无效定时器引用 |
| “Missing CDO” | 类默认对象(CDO)被GC回收 | 在构造函数中调用AddToRoot() |
⚡ 终极验证项目
- 创建继承UObject的自定义类,验证:
- 在BeginDestroy()中输出日志
- 通过AddToRoot()使其常驻内存
- 模拟资源异步加载回收:
- 用FStreamableManager加载资源后释放引用
- 观察GC是否回收UAsset对象
- 制造循环引用:
- 两个UObject相互持有TStrongObjectPtr
- 用OBJ REFS命令检查引用环
阅读记录
FGCCSyncObject GC 系统特有的用于多线程同步的核心类工具,UE的GC 标记是并行的,这个类的作用就是确保多线程并行都完成,用于防止 GC 的误清除或这内存的损坏,他是单例,全局只有一个
- 类的声明在 GCScopeLock.h
- 类函数的定义在 GarbageCollection.cpp
FReachabilityAnalysisState GReachabilityState; 实际的 garbageCollect 是通过这个类的 CollectGarbage(KeepFlags, bPerformFullPurge);来执行的
CSV_CUSTOM_STAT UE 中用于自定义性能监控数据的核心宏之一,属于UE的 CSV 性能分析系统(Comma-Separated Values Profiler)
FMemory::Trim(); UE内存管理系统的核心函数之一,它的主要作用是主动释放引擎内部内存分配器保留的未使用内存,整理内存碎片,建议调用间隔大于 30s
FUObjectItem 这个结构体包含了 UObject 的可达性flag
EInternalObjectFlags 内部的物体标签enum,包含了可达性flag
GIsIncrementalReachabilityPending 标记增量可达性分析是否在进行中