So I have a c++ function called from bp that creates an ‘latent action’ and sometimes it crashes due to FString& passed as param from bp no longer being valid at time when it’s being used in lambda. How do I check if it’s still valid?
I suspect that what you’re describing isn’t what you should be trying to do, but I can’t be sure. You should share the code of the function that is being called so that specific issues can be pointed out.
void FindUser(FString Email, FLatentActionInfo LatentInfo, FString& EntityId)
{
FCULatentAction *LatentAction = FCULatentAction::CreateLatentAction(LatentInfo, this);
if(!LatentAction)
return;
TSharedRef<IHttpRequest, ESPMode::ThreadSafe> HttpRequest = FHttpModule::Get().CreateRequest();
...
HttpRequest->OnProcessRequestComplete().BindLambda([this, LatentAction, &EntityId] ( FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful )
{
if ( bWasSuccessful && Response.IsValid() )
{
TSharedPtr<FJsonObject> JsonObject;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Response->GetContentAsString());
if (!FJsonSerializer::Deserialize(Reader, JsonObject)) {
UE_LOG(LogTemp, Log, TEXT("Failed deserialization"));
}
const auto UserInfo = JsonObject->GetObjectField("UserInfo");
const auto TitleInfo = UserInfo->GetObjectField("TitleInfo");
const auto TitlePlayerAccount = TitleInfo->GetObjectField("TitlePlayerAccount");
EntityId = TitlePlayerAccount->GetStringField("id");<--crash
}
LatentAction->Call();
});
HttpRequest->ProcessRequest();
}
Afaik you simply cannot check this.
Capturing local variables or function parameters by reference is a recipe for disaster, unless your lambda is only executed locally for a sync operation.
You should just capture by value
BindLambda([=](...) {
});
it ain’t my code, just trying to prevent it from crashing I guess passing an object that this string belongs to and first check if it’s valid before attempting to set the string would do the trick?
No it won’t because the reference there isn’t (necessarily) a reference to an object of any sort, it’s more likely a reference to something on the stack.
As Chatouille said, capturing function locals or parameters by reference is a no-no and you should change it to capturing by value. I would just get rid of the ‘&’ part of the EntityId capture instead of capturing everything with the ‘=’ as they suggested, but either way the result is the same.
tried the suggestions, ended up with
if (context != nullptr)
EntityId = TitlePlayerAccount->GetStringField(“id”);
else return;
where context is UObject* passed to FindUser
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.