Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UE] Bug: DynamicDelegate作为参数传递时可能造成UObject泄露 #1978

Open
3 tasks done
BlurryLight opened this issue Feb 12, 2025 · 1 comment · May be fixed by #1979
Open
3 tasks done

[UE] Bug: DynamicDelegate作为参数传递时可能造成UObject泄露 #1978

BlurryLight opened this issue Feb 12, 2025 · 1 comment · May be fixed by #1979
Assignees
Labels
bug Something isn't working Unreal

Comments

@BlurryLight
Copy link
Contributor

前置阅读 | Pre-reading

Puer的版本 | Puer Version

master

UE的版本 | UE Version

5.3

发生在哪个平台 | Platform

All

错误信息 | Error Message

No response

问题重现 | Bug reproduce

问题描述

当把JsFunction作为delegate传递时(比如通过toDelegate),如果绑定的Outer是一个生命周期很长的对象(UWorld / GameInstance / Subsystem)之类的,会在每次调用的时候创建一个新的UDelegateProxy,当调用足够频繁或者持续时间较长,会最终超过UE最大的UObject数量限制而崩溃。

Image

复现步骤

// header
DECLARE_DYNAMIC_DELEGATE(FSimpleDynamicDelegate);

UFUNCTION(BlueprintCallable)
static void CallSimpleDynamicDelegate(const FSimpleDynamicDelegate& DelegateCallback);

// cpp
void UTPBlueprintFunction::CallSimpleDynamicDelegate(const FSimpleDynamicDelegate& DelegateCallback)
{
	DelegateCallback.ExecuteIfBound();
}

ts代码:

import { $InRef, $Ref, $ref, $unref, toDelegate } from 'puerts';
import * as UE from 'ue';
import { rpc } from 'ue';

class MyPlayerController extends UE.PlayerController
{
    ReceiveBeginPlay(): void
    {
        this.CallbackEvent = toDelegate(this, this.FooCallback.bind(this));

        for(let i = 0; i < 1000; i++)
        {
            UE.TPBlueprintFunction.CallSimpleDynamicDelegate(this.CallbackEvent);
        }
    }

    ReceiveTick(DeltaSeconds: number): void {
        UE.TPBlueprintFunction.CallSimpleDynamicDelegate(this.CallbackEvent);
    }


    //@no-blueprint
    FooCallback() : void
    {
        console.log("FooCallback");
    }

    private CallbackEvent: UE.$Delegate<() => void>;

}

export default MyPlayerController;

当带着这个PlayerController启动游戏,随着时间推移,SysObjectRetainer内保存的UDynamicDelegateProxy会越来越多,而且永远不会释放。

@BlurryLight BlurryLight added bug Something isn't working Unreal labels Feb 12, 2025
@BlurryLight
Copy link
Contributor Author

看了下,toManualReleaseDelegate不会有这个问题,因为ManualReleaseCallbackMap做了去重。我试着改下

@BlurryLight BlurryLight linked a pull request Feb 12, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Unreal
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants