DEV Community

Attilio Carotenuto
Attilio Carotenuto

Posted on

Analysing crash dumps

Crash dumps, also referred to as memory dumps or core dumps, are diagnostic files containing a variety of information about a program state that help developers identify and troubleshoot bugs, crashes and general issues.

Their name and content can vary depending on the information they include, and the state of the program while they were captured. Memory dumps, despite the name, are not limited to memory, but normally include registers, stacks, threads information, callstacks and more. Core dumps are normally taken when a single process crashes, while Full Memory dump, or System Dump, captures everything in the target scope, such as full virtual memory of the process. Minidumps, on the other hand, contain a smaller subset of information, enough to do stack trace analysis. These names are often used interchangeably, and each operating system calls them a bit differently.

While they are referred to as crash dumps, as they are often taken when an application crashes, they can be taken at any moment during the application lifetime. Memory dumps taken while the application is still running are often called Live Dumps. Spin dumps, on the other hand, are used to investigate hangs and performance issues, and contain data sampled over an interval of time, often while the game is still running or unresponsive.

There are also considerations regarding filesize, as crash dumps are often shared from external users or automatically uploaded to a dashboard. Minidumps are relatively small and are normally used for this reason, while Core dumps and Memory dumps can be very large, often containing multiple GBs of data.

Crash Dumps are a useful tool to understand why a crash happened and fix it, but they can be intimidating to use at first. Let’s see how we can generate and analyse them.

Retrieving a Crash Dump when your game crashes

Whenever your game crashes, Unity will create a crash report in the %TMP%\CompanyName\ProductName\Crashes directory, containing the Player logs, and a minidump file, which contains registers, stack, and portions of memory. If the crash originated from within the editor, it will be stored in the %TMP%\Unity\Editor\Crashes directory on Windows.

Similarly, Unreal Engine will store crash reports, including dump files, in the C:\Users[username]\AppData\Local[Project Name]\Saved\Crashes directory, or in the project’s Saved/Crashes folder if the crash originated in the editor.

As all developers can attest, making your game crash is not particularly hard. Still, most game engines have ways to simulate crashes in a deterministic and safe way, for testing purposes.

In Unity, you can manually cause a crash by calling UnityEngine.Diagnostics.Utils.ForceCrash and specifying the crash category (AccessViolation, FatalError, Abort, or PureVirtualFunction). Calling this while in Editor Play Mode will cause the whole editor to crash, so make sure to put some safeguards around it and always save your work before testing.

While working in Unreal Engine, you can explicitly cause a crash by using one of the Asserts functions, such as check(false) or checkNoEntry(), or by calling UE_LOG with Fatal verbosity.

Generating a memory dump on Windows

By default, Windows does not create a memory dump when an application crashes (unless it does that explicitly, such as with Unity and Unreal). We can change this by setting up Windows Error Reporting. To do so, follow these steps:

  • Open the Registry Editor
  • Go to the key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps
  • Create, or edit if existing, the DumpFolder value (using Expandable String value, or REG_EXPAND_SZ), and set its value to a directory where you want to store your dumps.
  • Create a DumpType value (as REG_DWORD), to define what memory dump type you’d like to generate. By default, Windows will generate Mini dumps if this is not set. Possible values are: 0: Custom dump 1: Mini dump 2: Full dump
  • Optionally create a DumpCount key (as REG_DWORD), and set how many memory dumps you’d like to store. When this limit is exceeded, older files are overwritten. By default, Windows will store 10 files if the key is not set.

Registry Editor

You can also set specific settings for each application, by creating a new specific registry key for your application, for example HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\CrashTest.exe. Windows will use the global values first, and then override them with these specific values, if found.

You can generate a memory dump while an application is still running, or hanging, by opening the Windows Task Manager, right clicking on the related process, and selecting “Create Memory Dump File”.

Windows Task Manager

This will contain all application memory, so the resulting file can be quite large. These are also called user-mode memory dumps as they contain data for a specific process, rather than the whole system (kernel memory dumps).

Other alternative tools for generating and analysing crash dumps on Windows are dotnet-dump and ProcDump.

Generating a Memory Dump on Mac

On Mac, crash dumps are also disabled by default (as on Windows, unless the application does that explicitly, such as with Unity and Unreal). In order to generate dump files when an application crashes, you first need to run:

ulimit -c unlimited

Then set the coredump filename pattern. For example, this will store them in the tmp/cores folder and append the executable name, the process ID, and the UNIX timestamp to the filename:

kernel.core_pattern=/tmp/cores/core.%e.%p.%t

Crash dumps are quite large, so you can quickly run out of disk space. You can disable them back, when you are done debugging, by running:

ulimit -c 0

Whenever your game crashes, a new entry will be created in the Crash Reports section of the Console app.

Mac Console App

You also have the option to create a so-called Spindump. They are mainly used to investigate unresponsive apps, and typically contain multiple stack traces collected over ~10 seconds for one or all processes. They are generated automatically whenever you Force Quit an application that was unresponsive, and stored in the Spin Reports section of the Console app.

You can manually create a spindump file by opening the Activity Monitor, looking for your game process, then opening the More menu at the top and selecting Spindump.

Activity Monitor

All report files are stored in the Library/Logs/DiagnosticReports folder.

Analysing with WinDbg

While on Windows, you can analyze dump files using WinDbg. You can find it here.

You can then open a dump file by going to File > Open Dump File.

As mentioned earlier, dump files can contain different amounts and types of information, depending on how they are generated. The command window will inform you about the kind of memory dump file you loaded, what it contains,and allows you to run commands to query it.

After loading the dump file, WinDbg will do some preliminary checks, including what it contains, whether it has a breakpoint exception stored in it, and some metadata:

Loading Dump File [C:\Users\attiliocarotenuto\AppData\Local\Temp\DefaultCompany\CrashTest\Crashes\Crash_2025-08-19_082728710\crash.dmp]
User Mini Dump File: Only registers, stack and portions of memory are available
Enter fullscreen mode Exit fullscreen mode

First thing you want to do is run the sympath command, and pass your game directory, so WinDbg can access the relevant DLL and symbol files.

.sympath+ "C:\Users\attiliocarotenuto\Desktop\CrashTest"

Whenever you change these paths, make sure to run .reload so WinDbg can load newly found symbol files.

Then, as recommended by the initial prompt, you want to run the analyze command, in verbose mode:

!analyze -v

This will show the crash reason, which module initiated the crash, and the stack trace if available.

If the application did not crash but was hanging, you can add the -hang modifier to the analyze command to run specific analysis, such as whether threads are blocking other threads. Make sure to switch to the thread that you believe caused the issue beforehand, from the Threads tab.

You can run the “k” command to show the stacktrace:

0:000> k
  *** Stack trace for last set context - .thread/.cxr resets it
 # Child-SP          RetAddr               Call Site
00 000000ef`db90d800 00007ffb`a8451af9     UnityPlayer!DebugStringToFilePostprocessedStacktrace+0xb0e
01 000000ef`db90d8f0 00007ffb`a74baca4     UnityPlayer!DebugStringToFile+0x6d9
02 000000ef`db90dad0 00007ffb`a6687033     UnityPlayer!DiagnosticsUtils_Bindings::ForceCrash+0xb4
03 000000ef`db90db70 000002ae`30eb5340     UnityPlayer!Utils_CUSTOM_ForceCrash+0x83
04 000000ef`db90dc10 00000000`00000000     0x000002ae`30eb5340
Enter fullscreen mode Exit fullscreen mode

If you want information about a specific type, you can use the “dt {type}” command.

If you are interested in the modules, you can use the “lm” command to show the loaded modules.

start             end                 module name
00000000`00400000 00000000`0041e000   xinput1_3   (deferred)             
000002ae`32690000 000002ae`326a6000   umppc20403   (deferred)             
000002ae`326d0000 000002ae`326e4000   CsXumd64_20403   (deferred)             
00007ff7`bee80000 00007ff7`bef29000   CrashTest   (deferred)             
00007ffb`a5b40000 00007ffb`a6583000   mono_2_0_bdwgc   (deferred)             
00007ffb`a6590000 00007ffb`aa0d4000   UnityPlayer   (pdb symbols)          C:\ProgramData\Dbg\sym\UnityPlayer_Win64_player_development_mono_x64.pdb\09C8D9C2027E45AAB4CDC87B30D02D651\UnityPlayer_Win64_player_development_mono_x64.pdb
00007ffc`87b80000 00007ffc`87bf8000   lib_burst_generated   (deferred)            
[...]
Enter fullscreen mode Exit fullscreen mode

You can optionally run “lm” in verbose mode by adding the “v” modifier, then it will print additional information for each loaded module, such as the Mapped memory image file, its size, version, checksum and so on.

On the bottom right, you can switch to the Stack tab and analyse the callstack that caused the crash.

Stack

If you don’t see readable names here, make sure you set up the source and symbol files correctly, as covered earlier.

You can print all threads by running the ~ command, including their state

Analysing crash dumps with Visual Studio 2022

While debugging with Visual Studio, you can generate a dump file whenever the debugger stops at a breakpoint or exception, by selecting Debug > Save Dump As. This is particularly convenient when you want to resume the debugging session later on, or share it with other developers.

You can choose to save the file with heaps, with variables values and loaded native modules binaries included, which makes it easier to debug, especially when you later don’t have the app binary. Alternatively, you can save without heaps, which will result in a smaller file, but will only contain stack variables values, and it will require loading the app binaries to connect symbols.

You can only generate a dump file when debugging a native process, the option will be disabled when looking at managed code, for example while using the Unity debugger rather than native debugger.

To load a crash dump you can select Debug > Debug Dump File, or drag the dump file directly into the Visual Studio window. It will then show a summary of its content which, depending on the type of dumpfile you selected, will include threads, modules, symbol paths, stack frames, and even a screenshot of the game just before it crashed.

Here is a Core Dump with everything already set and included for debugging.

Core Dump

In this case, I can just press Debug from the Actions pane, which will initialise the debugger, load the executable along with symbols, and navigate directly to the relevant code that triggered the crash, along with its callstack and threads. If Visual Studio cannot find the related executable, it will prompt you to navigate and select it manually.

You can open the Locals and Autos windows, from Debug > Windows, to inspect the value of the variables, within the current scope, when the game crashed. You can also look at raw data by opening the Memory window under Debug > Windows > Memory.

To check the modules, open the related window from Debug > Windows. Here, Visual Studio will indicate whether the required symbols are loaded. If they are missing, you can right-click on a module, select Load Symbols, and supply the symbols file.

Visual Studio Symbols

Here is another example with a minidump, generated by manually crashing a Unity game. As you can see, it has less data included.

Minidump

The first thing you want to do is to ensure symbols are correctly setup, using the “Set symbol paths” action on the right panel. You can then start a debugging session using the actions listed on the right pane.

Analysing crash dumps with Rider

To inspect crash dumps in Rider, you need to create a new Run/Debug configuration, using Native Core Dump Debug as type, and set the Core dump path and the executable path. You can then set the paths where Rider should look for the related binaries, within Binaries Search Paths.

Then, start the Debugging session. As always, the amount of information and capabilities will depend on the content of the memory dump you’ve loaded, such as callstacks, variable values and so on.

Rider will load the Disassembly window, as well as the Threads & Variables window at the bottom, where you can inspect the call stack and variables.

Rider Threads & Variables

The Modules tab will show loaded modules, and indicate whether the related symbols are loaded. You can right click on a module and select Load Symbols to provide missing symbols, although this is only available while using the .NET debugger. Symbols can’t be loaded while the debugger is running, so they need to be set up beforehand.

Rider Modules

Rider has a more limited set of features compared to Visual Studio when it comes to crash dump debugging, for this reason it’s recommended to use Visual Studio if possible.

Top comments (0)