UE4.27使用TSharedPtr销毁持有的蓝图生成Actor时触发断言异常问题
问题根因
你触发断言的核心原因是:UE的UObject(包括所有AActor子类)的生命周期由引擎自带的垃圾回收(GC)系统统一管理,完全不支持用TSharedPtr这类原生C++智能指针持有。TSharedPtr的引用计数逻辑和UE GC体系完全独立,你调用SharedPointerObjectPtr.Reset()时,TSharedPtr会直接delete所持有的Actor内存,完全绕过了UE销毁UObject的标准流程:UE要求销毁UObject前必须先清理引擎侧绑定的名称、标记、生命周期状态,其中就包括将对象名重置为NAME_None,直接delete没有执行这步逻辑,自然就触发了GetFName() == NAME_None的断言。
修复方案
UE针对UObject类型提供了专门的指针方案,不要用TSharedPtr持有UObject对象:
- 如果你需要持有强引用、阻止GC回收对象,直接用被
UPROPERTY()标记的裸指针即可,UE GC会自动扫描标记了该宏的指针,只要指针不为空就不会回收所持对象。 - 如果你只需要弱引用、不想影响GC回收逻辑,使用UE专门为UObject设计的弱指针
TWeakObjectPtr即可。
代码修改示例
1. 指针定义修改(APointersManager.h)
// 强引用方案:加UPROPERTY标记 UPROPERTY() APointerReferencedActor* SharedPointerObjectPtr = nullptr; // 弱引用方案:用TWeakObjectPtr,不需要加UPROPERTY // TWeakObjectPtr<APointerReferencedActor> SharedPointerObjectPtr;
2. 赋值逻辑不变
SharedPointerObjectPtr = Cast<APointerReferencedActor>(GetWorld()->SpawnActor(SharedPointerClass));
3. 释放&销毁逻辑修改
不要靠智能指针的Reset销毁对象,主动调用Actor的Destroy()方法走引擎标准销毁流程:
// 先判断对象是否有效 if (IsValid(SharedPointerObjectPtr)) { // 走引擎标准销毁流程 SharedPointerObjectPtr->Destroy(); // 清空指针引用,方便GC回收 SharedPointerObjectPtr = nullptr; }
额外注意
TSharedPtr、TUniquePtr这类UE提供的通用智能指针,仅用于持有非UObject派生的原生C++对象,不要和UObject体系混用,否则要么触发断言崩溃,要么出现野指针访问问题。
内容的提问来源于stack exchange,提问作者Bisher Dokkmak
相关产品推荐
相关产品推荐

