SharedStruct内の構造体でSharedStructを使うと入れ子になっているSharedStruct内で保持しているオブジェクトがGCで流されてしまう

いつもお世話になっております。

表題の通りSharedStructが入れ子になっていると、子のSharedStructで保持している構造体内にあるオブジェクトがGCで流されてしまいます。

SharedStructのAddStructReferencedObjectsの処理を以下のようにすれば、GCによって流されないことを確認しています。

void FSharedStruct::AddStructReferencedObjects(class FReferenceCollector& Collector) const
{
	if (auto* Struct = GetScriptStructPtr(); Struct && *Struct)
	{
#if 1
		Collector.AddReferencedObject(*Struct);
		Collector.AddPropertyReferencesWithStructARO(*Struct, const_cast<uint8*>(GetMemory()));
#else
		Collector.AddReferencedObjects(*Struct, const_cast<uint8*>(GetMemory()));
#endif
	}
}

下記のAGCTestActorをレベル上に配置してPIEを開始すると同様の現象が起きます

UCLASS()
class UTestObject : public UObject
{
	GENERATED_BODY()
public:
	UPROPERTY()
	FString String;
};
 
USTRUCT()
struct FObjectHolder_Base
{
	GENERATED_BODY()
public:
	virtual ~FObjectHolder_Base() = default;
 
	virtual bool IsUnreachable() const
	{
		return true;
	}
};
 
USTRUCT()
struct FObjectHolder_TestObject : public FObjectHolder_Base
{
	GENERATED_BODY()
public:
	UPROPERTY()
	TObjectPtr<UTestObject> Object;
 
	FObjectHolder_TestObject()
	{
		Object = NewObject<UTestObject>();
	}
 
	virtual bool IsUnreachable() const override
	{
		return Object->IsUnreachable();
	}
};
 
USTRUCT()
struct FObjectHolderWrapper
{
	GENERATED_BODY()
public:
	UPROPERTY()
	FSharedStruct Holder;
 
 
	FObjectHolderWrapper()
	{
		Holder.InitializeAs<FObjectHolder_TestObject>();
	}
 
	bool IsUnreachable() const
	{
		if (const FObjectHolder_Base* HolderPtr = Holder.GetPtr<FObjectHolder_Base>())
		{
			return HolderPtr->IsUnreachable();
		}
		return true;
	}
};
 
UCLASS()
class AGCTestActor : public AActor
{
	GENERATED_BODY()
protected:
	UPROPERTY()
	FSharedStruct SharebleHolder;
 
	AGCTestActor()
		: Super()
	{
		PrimaryActorTick.bCanEverTick = true;
 
		SharebleHolder.InitializeAs<FObjectHolderWrapper>();
	}
 
	virtual void Tick(float DeltaTime)
	{
		Super::Tick(DeltaTime);
	
		if (FObjectHolderWrapper* WrappedHolder = SharebleHolder.GetPtr<FObjectHolderWrapper>())
		{
			if (WrappedHolder->IsUnreachable())
			{
				UE_LOG(LogTemp, Display, TEXT("IsUnreachable"));
			}
		}
	}
 
	UFUNCTION(CallInEditor)
	void ForceGarbageCollection()
	{
		GEngine->ForceGarbageCollection();
	}
};

UE5.8のコードも確認しましたが、今使用しているUE5.6と同じ処理になっていたため恐らくUE5.8でも同現象は起きると思います。

お聞きしたいのは以下の2点です。

・この修正で問題ないでしょうか。

・もしこの修正に問題があるなら、どういった修正方法がよいでしょうか。

お手数をおかけしますが、お目通しいただければ幸いです。

[Attachment Removed]

お世話になっております。

ご指摘ありがとうございます。

> ・この修正で問題ないでしょうか。

> ・もしこの修正に問題があるなら、どういった修正方法がよいでしょうか。

現在開発チームに情報共有を行っている最中ですが、修正内容につきましては、FInstancedStruct::AddStructReferencedObjects() の実装が同様のものになっていることからも、ご提示いただいた修正内容で問題ございません。

また、大変お手数ながら同様の修正を FConstSharedStruct にも行っていただく必要がございます。

取り急ぎお返事申し上げます。

以上、よろしくお願いいたします。

[Attachment Removed]

ご回答ありがとうございます。​

ではこの対応で ​FSharedStruct、FConstSharedStruct の修正を行おうかと思います。

[Attachment Removed]

ご確認ありがとうございました。

大変お手数ですが、ご提示の内容でお手元のエンジンの修正をお願いいたします。

本件は社内のトラッカーに起票し、エンジン側でも(少々期間を頂戴いたしますが)同様の対応を行う予定です。​

それでは本件は回答済みとしてCloseさせていただきます。

​問題のご共有、誠にありがとうございました。

また何か疑問点や不明点などございましたら、お気軽にEPSをご利用ください。​

[Attachment Removed]