How do I properly destruct a nested TArray?

I have a nested TArray with an explicit allocator:

TArray< TArray< TArray< FVoxelData, TInlineAllocator<16> > > > voxels;

FVoxelData has a pointer to an AActor and stores a FIntVector. I’m seeing the editor crash when it destructs the object that holds the voxels member variable. Since I can’t use UPROPERTY() with my multidimensional voxels Tarray, I assume I need to implement my own destructor.

I’m new to c++ programming, but not programming in general. I never used the new keyword in any of my code, so I’m not sure what I would be implementing in the destructor. Can anyone help? Or am I completely off base here and I don’t need to write a destructor?

This is the crash log I’m seeing:

Access violation - code c0000005 (first/second chance not available)

UE4Editor_Core!rml::internal::Block::findObjectSize()
UE4Editor_Core!FMallocTBB::Free() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\core\private\hal\malloctbb.cpp:109]
UE4Editor_Core!FMemory::Free() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\core\public\hal\fmemory.inl:49]
UE4Editor_VRBuildingGame_2133!TArray<TArray<TArray<FVoxelData,TInlineAllocator<16,FDefaultAllocator> >,FDefaultAllocator>,FDefaultAllocator>::~TArray<TArray<TArray<FVoxelData,TInlineAllocator<16,FDefaultAllocator> >,FDefaultAllocator>,FDefaultAllocator>() [c:\program files (x86)\epic games\4.12\engine\source\runtime\core\public\containers\array.h:723]
UE4Editor_VRBuildingGame_2133!TSparseArray<TSetElement<TPair<FIntVector,FChunk> >,TSparseArrayAllocator<FDefaultAllocator,FDefaultBitArrayAllocator> >::Empty() [c:\program files (x86)\epic games\4.12\engine\source\runtime\core\public\containers\sparsearray.h:219]
UE4Editor_VRBuildingGame_2133!ATheGrid::~ATheGrid()
UE4Editor_VRBuildingGame_2133!ATheGrid::`vector deleting destructor'()
UE4Editor_CoreUObject!IncrementalPurgeGarbage() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\coreuobject\private\uobject\garbagecollection.cpp:1042]
UE4Editor_CoreUObject!CollectGarbageInternal() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\coreuobject\private\uobject\garbagecollection.cpp:1321]
UE4Editor_CoreUObject!CollectGarbage() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\coreuobject\private\uobject\garbagecollection.cpp:1341]
UE4Editor_UnrealEd!FKismetEditorUtilities::CompileBlueprint() [d:\build\++ue4+release-4.12+compile\sync\engine\source\editor\unrealed\private\kismet2\kismet2.cpp:807]
UE4Editor_Kismet!FBlueprintEditor::Compile() [d:\build\++ue4+release-4.12+compile\sync\engine\source\editor\kismet\private\blueprinteditor.cpp:3184]
UE4Editor_Kismet!TBaseSPMethodDelegateInstance<0,FBlueprintEditor,0,TTypeWrapper<void> __cdecl(void)>::Execute() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\core\public\delegates\delegateinstancesimpl_variadics.inl:321]
UE4Editor_Kismet!TBaseSPMethodDelegateInstance<0,FBlueprintEditor,0,void __cdecl(void)>::ExecuteIfSafe() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\core\public\delegates\delegateinstancesimpl_variadics.inl:427]
UE4Editor_Slate!FUICommandList::ExecuteAction() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\slate\private\framework\commands\uicommandlist.cpp:87]
UE4Editor_Slate!SToolBarButtonBlock::OnClicked() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\slate\private\framework\multibox\stoolbarbuttonblock.cpp:300]
UE4Editor_Slate!TMemberFunctionCaller<SToolBarButtonBlock,FReply (__cdecl SToolBarButtonBlock::*)(void) __ptr64>::operator()<>() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\core\public\delegates\delegateinstanceinterface_variadics.h:161]
UE4Editor_Slate!TTupleImpl<TIntegerSequence<unsigned int> >::ApplyAfter_ExplicitReturnType<FReply,TMemberFunctionCaller<SToolBarButtonBlock,FReply (__cdecl SToolBarButtonBlock::*)(void) __ptr64> >() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\core\public\delegates\tuple.h:128]
UE4Editor_Slate!TBaseSPMethodDelegateInstance<0,SToolBarButtonBlock,0,FReply __cdecl(void)>::Execute() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\core\public\delegates\delegateinstancesimpl_variadics.inl:321]
UE4Editor_Slate!TBaseDelegate<FReply>::Execute() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\core\public\delegates\delegatesignatureimpl_variadics.inl:521]
UE4Editor_Slate!SButton::OnMouseButtonUp() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\slate\private\widgets\input\sbutton.cpp:275]
UE4Editor_Slate!<lambda_8d0e9a1da76abd0a756a3a9d775f5ed1>::operator()() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\slate\private\framework\application\slateapplication.cpp:4598]
UE4Editor_Slate!FEventRouter::Route<FReply,FEventRouter::FToLeafmostPolicy,FPointerEvent,<lambda_8d0e9a1da76abd0a756a3a9d775f5ed1> >() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\slate\private\framework\application\slateapplication.cpp:215]
UE4Editor_Slate!FSlateApplication::RoutePointerUpEvent() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\slate\private\framework\application\slateapplication.cpp:4587]
UE4Editor_Slate!FSlateApplication::ProcessMouseButtonUpEvent() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\slate\private\framework\application\slateapplication.cpp:5041]
UE4Editor_Slate!FSlateApplication::OnMouseUp() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\slate\private\framework\application\slateapplication.cpp:5021]
UE4Editor_Core!FWindowsApplication::ProcessDeferredMessage() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\core\private\windows\windowsapplication.cpp:1510]
UE4Editor_Core!FWindowsApplication::DeferMessage() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\core\private\windows\windowsapplication.cpp:1850]
UE4Editor_Core!FWindowsApplication::ProcessMessage() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\core\private\windows\windowsapplication.cpp:745]
UE4Editor_Core!FWindowsApplication::AppWndProc() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\core\private\windows\windowsapplication.cpp:667]
user32
user32
UE4Editor_Core!FWindowsPlatformMisc::PumpMessages() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\core\private\windows\windowsplatformmisc.cpp:903]
UE4Editor!FEngineLoop::Tick() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\launch\private\launchengineloop.cpp:2729]
UE4Editor!GuardedMain() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\launch\private\launch.cpp:148]
UE4Editor!GuardedMainWrapper() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:126]
UE4Editor!WinMain() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:200]
UE4Editor!__scrt_common_main_seh() [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:264]
kernel32
ntdll

If something is not a pointer in array it will be destroyed when you remove element from array, as non-pointer variables are data itself.

Statically allocated variables (the base array in your case) are can’t be deleted, but in case of arrays it can be emptied.

Without UPROPERTY(), engine don’t seerefrences to UObjects that varable contains, it means it can be deleted and if object is deleted you encounter nasiest existance in C++, invalid pointer. But since you don’t use nay pointers this should not be a issue at all

I never heard of TArray in TArray to work, so this may really cause a trouble. You saying you getting crashes so did you check the logs in Saved/Logs on what is actully happening?

you could create your own 3 dimentional array by making struct with single array and overriding [] operator with FVector argument (if i’m not mistaken you can use any type as operator argument). Let’s say we have cube of 64 on each axis, you create array with 646464 elements (262144), and every 64 elements of that single array will be different raw of Y-axis and every 4096 as new row of Z-axis. If oyu think baout it not makes much diffrence as array in array would allocate this in memory in similar way

TArrays of TArrays are fine in general, but not as UPROPERTY()s. If you try to do this as a UPROPERTY(), UnrealHeaderTool will throw an error, so at worst it won’t compile - there’s no danger of bad runtime behaviour here.

A TArray of a USTRUCT() containing a TArray is definitely the way to go if you want 2D behaviour working as a UPROPERTY().

Steve

Thanks for the help guys, that does clear a few things up. I don’t mind this TArray being blueprint inaccessible, but I do need it to not crash :smiley:

I do have pointers in in FVoxelData to an AActor, so it’s possible I’m getting a invalid/dangling pointer when Unreal gc’s the actor. Though, since my crashes are happening during destruction of my TArray, I don’t think that’s the particular problem in this case. I’ve added the crash log I’m seeing in case that helps.

I’ll look into operator overloading today. Maybe that will magically solve things. Though, I would like to understand how to handle cases like this (unless avoiding them is the most appropriate way), since there seem to be quite a lot of classes that are not UPROPERTY valid.