Proper way to deal with destroying a TFunction?

I’m having some issues with my code crashing the editor by running out of memory over time. As a termporary workaround I’ve found I can stop the crashes just by printing to the output log. Since, this only happens in subclasses that implement a TFunction. I Believe the TFunction is causing the oom overtime.

BaseDialogue Header:

    typedef TFunction<FName(void)> Condition;
    typedef TArray<FName> BranchValues;
    typedef TUnion<BranchValues, Condition> BranchTypes;
    
    USTRUCT(NotBlueprintable)
    struct FDialogueNode
    {
         GENERATED_BODY()
    
         BranchTypes branch;
         
         FDialogueNode() {}
         FDialogueNode(Condition condition)
         {
              branch.SetSubtype<Condition>(condition);
         }
    
         FDialogueNode(BranchValues nextNodes)
         {
              branch.SetSubtype<BanchValues>(nextNodes);
         }
    
         void Reset()
         {
              if(branch.HasSubtype<BranchValues>())
              {
                   BranchValues bv = branch.GetSubtype<BranchValues>();
                   bv.Empty();
              }
              else if(branch.HasSubtype<Condition>())
              {
                  Condition c = branch.GetSubtype<Condition>();
                  c.Unset();
              }

              branch.Reset();
         }
    }
    
    UCLASS(abstract)
    class DIALOGUES_API UBaseDialogue : public UActorComponent
    {
        GENERATED_BODY()
    
    public:
        UBaseDialogue();
        
        // Other methods that do stuff
    
    private:
        UPROPERTY()
        TMap<FName, FDialogueNode> dialogues;
        IGameTime *gameTime;
     }

BaseDialogue cpp:

void UBanter2afterthespiders::OnRegister()
{
    Super::OnRegister();
    gameTime = new GameTime();
    Condition c_0 = [this](void)->FName{ return (gameTime->Hour() < 19) ? 
         TEXT("0x01000001000000D4") : TEXT("0x01000001000000E2"); };
    dialogues.Emplace(TEXT("0x01000001000000DC"), FDialogueNode(c_0));

    // rest of the dialogue nodes left out.
}

void UBanter2afterthespiders::OnUnregister()
{
    Super::OnUnregister();
    for(auto it = dialogues.CreateIterator(); it; ++it)
        it.Value().Reset();
    // Delete pointers here
	dialogues.Empty();
    UE_LOG(LogTemp, Warning, TEXT("Stops engine from crashing"));
    delete gameTime;
}

IGameTime header:

class IGameTime
{
	public:
		virtual ~IGameTime() {}
		virtual int Hour() = 0;
};

I believe the issue I’m having is since TFunction needs an IGameTime when I call Unset(). Trying to delete IGameTime after Unset() causes a crash when the editor stops playing. If I don’t Unset TFunction everything exits fine, as long as I print to the console. Crashes happen even if I switch the order of calls to delete IGameTime, and Unset(), it just takes a few more plays in the editor.

How would I go about clearing out the TFunction correctly or fixing the oom issue?

Hi,

I don’t know if you’re still having a problem with this, but the proper way to unbind a TFunction is simply to assign it to nullptr:

c = nullptr;

Unset() is an implementation detail that should not be callable by user code - I’ll fix that.

Sorry for your troubles,

Steve

Thanks, that’ll probably clean up a memory leak that might be going on currently. I ended up finding out that the issue causing the crash actually had nothing to do with the TFunction it just triggered the conditions causing it. It was from using the copy constructor to assign a TUnion to a local variable. I ended up having to use the move constructor, with the Move method.