Removing delegate handle inside a lambda causes memory corruption

So i’ve noticed that if I remove a delegate using it’s delegate handle inside of a lambda, the remove call causes memory corruption and scribbles the this pointer inside the lambda. If I swap it out with a RemoveAll(), it doesn’t cause a problem. If I change it to not be a lambda function bound to a delegate, it also works.

I’ve highlighted the offending line. This is a snippet from AGameSession derived class’s FindSessions() member function. InternalOnFindSessionsCompleteDelegateHandle is a member FDelegateHandle property.

Am I missing something here or is this a bug in the deallocation?

InternalOnFindSessionsCompleteDelegateHandle = Sessions->AddOnFindSessionsCompleteDelegate_Handle(FOnFindSessionsCompleteDelegate::CreateLambda(
                [this, SearchSettingsRef](bool bWasSuccessful) {
                    UE_LOG(LogOnlineGame, Verbose, TEXT("OnFindSessionsComplete bSuccess: %d"), bWasSuccessful);

                    IOnlineSubsystem* const OnlineSub = IOnlineSubsystem::Get();
                    if (OnlineSub)
                    {
                        IOnlineSessionPtr Sessions = OnlineSub->GetSessionInterface();
                        if (Sessions.IsValid())
                        {
                            UE_LOG(LogOnlineGame, Verbose, TEXT("Num Search Results: %d"), SearchSettingsRef->SearchResults.Num());
                            for (int32 SearchIdx = 0; SearchIdx < SearchSettingsRef->SearchResults.Num(); SearchIdx++)
                            {
                                const FOnlineSessionSearchResult& SearchResult = SearchSettingsRef->SearchResults[SearchIdx];
                                DumpSession(&SearchResult.Session);
                            }

                            GetOnFindSessionsComplete().Broadcast(bWasSuccessful);
                            ***Sessions->ClearOnFindSessionsCompleteDelegate_Handle(this->InternalOnFindSessionsCompleteDelegateHandle);***
                        }
                    }
                }
            ));

Hi Ikrima,

The ‘this’ pointer is captured by the lambda and thus forms part of its memory footprint. When the lambda is destroyed, the ‘this’ pointer is destroyed along with it, and so any access through the ‘this’ pointer (or any lambda state access) after deletion will be undefined.

It’s unfortunate that ClearOnFindSessionsCompleteDelegate_Handle is defined to reset the handle that it was passed, or this would not be a problem. However, it’s probably too late to change now. I suggest you take a local copy of ‘this’ before removing the delegate.

Hope this helps,

Steve

Makes sense. Thanks for the answer