Crash on AbilitySystem Destruction on Alt+F4

On Alt + F4 this can randomly crash wit this stack trace. Not much more i can really say, its so random we have not been able to 100% repro.

DominanceTOE!FMallocBinned2::GetAllocationSize() [C:\Builds\DominanceBuild\Engine\Source\Runtime\Core\Public\HAL\MallocBinned2.h:498] DominanceTOE!FMallocPoisonProxy::Free() [C:\Builds\DominanceBuild\Engine\Source\Runtime\Core\Public\HAL\MallocPoisonProxy.h:79] DominanceTOE!FMemory::Free() [C:\Builds\DominanceBuild\Engine\Source\Runtime\Core\Public\HAL\FMemory.inl:166] DominanceTOE!TBaseUObjectMethodDelegateInstance<0,UAbilitySystemComponent,void __cdecl(FAggregator *),FDefaultDelegateUserPolicy,FGameplayAttribute,bool>::scalar deleting destructor’()
DominanceTOE!DestructItems<TDelegateBase,int>() [C:\Builds\DominanceBuild\Engine\Source\Runtime\Core\Public\Templates\MemoryOps.h:108]
DominanceTOE!FAggregator::~FAggregator() [C:\Builds\DominanceBuild\Engine\Plugins\Runtime\GameplayAbilities\Source\GameplayAbilities\Private\GameplayEffectAggregator.cpp:377]
DominanceTOE!SharedPointerInternals::TReferenceControllerWithDeleter<FAggregator,SharedPointerInternals::DefaultDeleter,1>::DestroyObject() [C:\Builds\DominanceBuild\Engine\Source\Runtime\Core\Public\Templates\SharedPointerInternals.h:375]
DominanceTOE!UE::Core::Private::Tuple::TTupleBase<TIntegerSequence<unsigned int,0,1>,FGameplayAttribute,FAggregatorRef>::~TTupleBase<TIntegerSequence<unsigned int,0,1>,FGameplayAttribute,FAggregatorRef>()
DominanceTOE!TSparseArray<TSetElement<TTuple<FGameplayAttribute,FAggregatorRef> >,TSparseArrayAllocator<TSizedDefaultAllocator<32>,FDefaultBitArrayAllocator> >::~TSparseArray<TSetElement<TTuple<FGameplayAttribute,FAggregatorRef> >,TSparseArrayAllocator<TSize() [C:\Builds\DominanceBuild\Engine\Source\Runtime\Core\Public\Containers\SparseArray.h:85]
DominanceTOE!FActiveGameplayEffectsContainer::~FActiveGameplayEffectsContainer() [C:\Builds\DominanceBuild\Engine\Plugins\Runtime\GameplayAbilities\Source\GameplayAbilities\Private\GameplayEffect.cpp:2881]
DominanceTOE!UAbilitySystemComponent::~UAbilitySystemComponent() [C:\Builds\DominanceBuild\Dominance\Intermediate\Build\Win64\DominanceTOE\Inc\GameplayAbilities\UHT\AbilitySystemComponent.gen.cpp:5736]
DominanceTOE!UDominanceAbilitySystemComponent::scalar deleting destructor'() DominanceTOE!FObjectPurge::DestroyObjects() [C:\Builds\DominanceBuild\Engine\Source\Runtime\CoreUObject\Private\UObject\GarbageCollection.cpp:827] DominanceTOE!IncrementalDestroyGarbage() [C:\Builds\DominanceBuild\Engine\Source\Runtime\CoreUObject\Private\UObject\GarbageCollection.cpp:4851] DominanceTOE!IncrementalPurgeGarbage() [C:\Builds\DominanceBuild\Engine\Source\Runtime\CoreUObject\Private\UObject\GarbageCollection.cpp:4528] DominanceTOE!UE::GC::PostCollectGarbageImpl<1>() [C:\Builds\DominanceBuild\Engine\Source\Runtime\CoreUObject\Private\UObject\GarbageCollection.cpp:5557] DominanceTOE!UE::GC::FReachabilityAnalysisState::PerformReachabilityAnalysisAndConditionallyPurgeGarbage() [C:\Builds\DominanceBuild\Engine\Source\Runtime\CoreUObject\Private\UObject\GarbageCollection.cpp:5746] DominanceTOE!CollectGarbage() [C:\Builds\DominanceBuild\Engine\Source\Runtime\CoreUObject\Private\UObject\GarbageCollection.cpp:5986] DominanceTOE!UEngine::TrimMemory() [C:\Builds\DominanceBuild\Engine\Source\Runtime\Engine\Private\UnrealEngine.cpp:16086] DominanceTOE!UEngine::LoadMap() [C:\Builds\DominanceBuild\Engine\Source\Runtime\Engine\Private\UnrealEngine.cpp:15676] DominanceTOE!UEngine::Browse() [C:\Builds\DominanceBuild\Engine\Source\Runtime\Engine\Private\UnrealEngine.cpp:15120] DominanceTOE!UEngine::TickWorldTravel() [C:\Builds\DominanceBuild\Engine\Source\Runtime\Engine\Private\UnrealEngine.cpp:15353] DominanceTOE!UGameEngine::Tick() [C:\Builds\DominanceBuild\Engine\Source\Runtime\Engine\Private\GameEngine.cpp:1774]

Steps to Reproduce
N/A

Hi,

Would you be able to provide any information you can think of regarding your project setup so we could attempt to infer repro conditions?

I.e. Does this happen in Play in editor or a packaged project or both?

Was your project on a previous version of UE where this only happened on 5.5?

Have you made any custom engine changes, particularly for garbage collection / memory management?

Do you happen to recall anything you were doing prior to hitting alt+f4 - it might be a race condition due to the randomness, like if an effect is still active.

Could you give a general overview on how you’re using the AbilitySystem component, for example is one actor accessing an Ability System Component that belongs to another actor, or actors being destroyed and respawned?

Thank you

Hey Daniel, we’re catching up on answering questions.

Looking at the callstack and especially ~FAggregator() I have a few thoughts:

  • Do you have any local modifications to FAggregator::~FAggregator()? Looking at the implementation I’m not sure where this line deeper in the callstack is coming from.

TBaseUObjectMethodDelegateInstance<0,UAbilitySystemComponent,void __cdecl(FAggregator *),FDefaultDelegateUserPolicy,FGameplayAttribute,bool>* If your ~FAggregator destructor is unchanged, another possibility is I suspect FScopedAggregatorOnDirtyBatch::EndLock() might be doing something risky with move semantics leaving the global DirtyAggregators variable in a bad state. I’ll gather thoughts internally on whether that needs fixing.

we have no changes

FAggregator::~FAggregator() { int32 NumRemoved = FScopedAggregatorOnDirtyBatch::DirtyAggregators.Remove(this); ensure(NumRemoved == 0); }Its so random, like complete random, probably 1 in 500 or more games someone will hit this. (listen server only not a client)

Thanks for that! We’re looking at it currently and realized that the TBaseUObjectMethodDelegateInstance could be FAggregator’s members being cleaned up so that explains that callstack entry.

Can you share the log message that it crashes with?

After discussing more internally, can you double check your codebase whether:

Double freeing

There is any double freeing going on - in particular of the DominanceAbilitySystemComponent. If that object is being assigned to any TSharedPtr/TSharedRef/TUniquePtr or explicitly deleted. Any class or struct holding a TSharedPtr to your ASC for example could possibly cause the ASC’s destructor to be called when the TSharedPtr is freed but ahead of any garbage collection pass.

For investigative purposes try overriding your ~UDominanceAbilitySystemComponent to check if anything destroys it outside of a GC pass:

UDominanceAbilitySystemComponent::~UDominanceAbilitySystemComponent() { check(GIsGarbageCollecting); }It’s also possible that FActiveGameplayEffectsContainer or an FAggregatorRef is being double freed if you manually created shared pointers/refs to any of those.

World teardown

Due to the nature of LoadMap being in the callstack: double check if any actor is attempting to spawn things, failing at that because World->bIsTearingDown and this crash being some side effect?

Never happened on 5.4, only 5.5.

Not changed anything, and we have a lot of ASC’s in the world (circa 2000ish) so its hard to know which one was the cause.

And it was on Alt + F4 so game exiting.

It never crashes in editor, was in packaged only. And its so rare like 1 in maybe 500 games. will hit this.

Thank you for the reply, I’ll go ahead and push this up to Epic to see if they can infer any repro conditions and assist with further troubleshooting. That being said their offices are closed until 7/14 and will get back to you as soon as possible.

Thank you for your patience!