DeferredPostLoadObjects多线程访问,有可能崩溃?

在项目中遇到一个崩溃,最终定位到FAsyncPackage::DeferredPostLoadObjects,以5.7代码为例:

  1. 在AsyncLoading6975行进添加到DeferredPostLoadObjects,此时是异步加载线程
  2. 在AsyncLoading.cpp:7038 访问DeferredPostLoadObjects,此时是主线程。

<br/>

<br/>

<br/>

在并行时,TArray的Add会添加一个AddUninitialized,然后再初始化。 在Get时,如果DeferredPostLoadIndex恰好是在AddUninitialized后,并且AsyncLoading.cpp:7038的Get正好在初始化前的情况下,是不是会触发一个多线程问题。

<br/>

问题出现是概率不大,如果确认是上面问题,有什么修复方法吗?

如果我们考虑加锁或原子操作,会不会导致异步加载回调变慢 ?

6975: DeferredPostLoadObjects.Add(Object);
7038  UObject* Object = DeferredPostLoadObjects[DeferredPostLoadIndex++];


<br/>

重现步骤

您好,如果是多线程导致的崩溃一般来说您可以将对应堆栈或者重现方式等信息进行反馈,我这边根据具体情况看是否引擎能在后面的版本中修复。

不过从您的分析上来看,我觉得加锁可以避免这种竞态崩溃,对于性能来说,看起来只是​TArray的Add和索引访问时加锁,时间复杂度很低持锁时间很短,一般不会高频并发,应该还好

目前只重现一次,从堆栈上看是从主线程的PostLoad开始,到某一个对象GetName出现的崩溃。 而且不能在TArray的Add时加锁,子线程需要在一帧内调用完PostLoadDeferredObject,否则主线程判断 TArray的数量为失败。所以担心会出现子线程频繁占用,导致主线程卡住的状态。

Epic Pro Support Community<[Content removed]> 在 2025年12月4日 周四 14:29 写道:

 Baokang Chen (Epic Games) 

您好,如果是多线程导致的崩溃一般来说您可以将对应堆栈或者重现方式等信息进行反馈,我这边根据具体情况看是否引擎能在后面的版本中修复。

不过从您的分析上来看,我觉得加锁可以避免这种竞态崩溃,对于性能来说,看起来只是​TArray的Add和索引访问时加锁,时间复杂度很低持锁时间很短,一般不会高频并发,应该还好

视图/答案 或回复此电子邮件

回复

DeferredPostLoadObjects多线程访问,有可能崩溃?

 瑞卿 孔 (EPS Member) 

星期二, 十二月 2, 2025 8:47 上午

重现步骤

Baokang Chen (Epic Games)

您好,如果是多线程导致的崩溃一般来说您可以将对应堆栈或者重现方式等信息进行反馈,我这边根据具体情况看是否引擎能在后面的版本中修复。

不过从您的分析上来看,我觉得加锁可以避免这种竞态崩溃,对于性能来说,看起来只是​TArray的Add和索引访问时加锁,时间复杂度很低持锁时间很短,一般不会高频并发,应该还好

星期四, 十二月 4, 2025 1:29 上午

当有人“在帖子上评论”时,您将收到电子邮件。

要更改或关闭 Epic Pro Support Community 电子邮件,登录 作为 [Content removed]。

是否对有关此帖子的通知感到厌烦?使用词语 " mute " 回复此电子邮件。

Epic, Epic Games, Unreal, Unreal Developer Network, UDN, Unreal Engine, UE4, and UE5 are trademarks or registered trademarks of Epic Games, Inc. in the United States of America and elsewhere. Epic Games, Inc., 620 Crossroads Blvd, Cary, NC 27518.

如果是这样的话可以考虑把主线程读取TArray数量的操作用读取一个原子计数器来代替