Here are some tips for debugging crashes in UE. Most of these are going to require you to be running a C++ Editor build from inside an IDE like Visual Studio, that has an integrated debugger. These are tips for "CPU" crashes, ie in your code or engine/editor C++ code. If you have a "GPU" crash (ie you get some message about GPUCrash, D3D, or DXGI) there are GPU-specific tools, eg see this page in the UE docs.
[0] Always run in a Debug build configuration when trying to track down crashes, if you can. In Visual Studio this would be something like DebugGame Editor (if using a launcher binary build) or Debug Editor (if using a source build). This will make many aspects of the debugger work much better, eg variables will be inspectable, etc. But it will also make everything much slower, and if you are using an Engine source build it might be mean a new engine compile (long!), so see below for another option.
[1] Enable Garbage Collection every frame. This can be done with the console command
gc.CollectGarbageEveryFrame 1
This can help to locate crashes where you are using a UObject (Actor, Component, etc) after it has been GC'd. Note that (at least in 5.3) this will result in some log spam from LogUObjectHash, which can be hidden using the Filters dropdown in the Log window.
[2] Run with the Memory Stomp Allocator. This can be done by adding the following argument to your startup command line (ie for running the Editor, game, etc).
-stompmalloc
The Stomp Allocator will result in invalid addresses being written to memory as soon as it is freed, which can help to pinpoint mystery crashes (in particular if you are finding crashes at different locations). This doesn't require any kind of engine rebuild to enable, so it may work in a Development build, although the stack/variables at the crash location may still be garbage.
[3] Selectively disable optimization by wrapping functions in UE optimization macros like this:
PRAGMA_DISABLE_OPTIMIZATION
void MyClass::MyFunc(int x)
{ /*...*/ }
PRAGMA_ENABLE_OPTIMIZATION
These C++ macros will disable optimization for a specific function. Note that they must go before & after a single function, and they don't work with templates. These tags will work in Development builds, and possibly even Shipping, and they don't require an Engine recompile. It is also possible to add/remove them while using LiveCoding, which can be incredibly helpful when trying to track down hard-to-reproduce issues.
[4] Delete your DDC folder. This is a sort of last-ditch thing, but especially if you are working with code for custom assets and you have (eg) been doing things like adding or removing properties, doing any custom serialization, etc, sometimes the cached data in the DDC can end up in a broken state which will result in mystery crashes.
(Note that if you are in a multi-user environment you might be using a shared DDC, which can result in lots of problems if you are locally changing code for assets/etc that might end up in the DDC for other users. You should run with -DDC=NoShared in this case)
[5] Reduce multi-threading. If you are having crashes where the stack contains many 'Task'-related functions, your crash is happening off the game thread, and possibly on the render thread. However it's also often the case that this isn't actually where the problem is, ie something in the game-thread code has trashed memory and the debugger location will be random. There are various command-line arguments for the Editor/Game that will reduce the amount of multithreading which can help to simplify the situation. The classic is
-onethread
...but note that this does not actually limit the entire engine to one thread, and (looking at the engine code) is now considered a legacy option that only disables the render thread. Search for 'thread' on this page in the documentation to find many other threading-related options to experiment with: https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-engine-command-line-arguments-reference
have fun debugging!