DayZDiag_x64 1.30.164.200 crashes as soon as Statistics > General is set to "all" if the PC has no audio output device. The stats overlay's XAudio2 line calls GetPerformanceData on the audio engine's XAudio2 interface without checking it for null. With no audio device that pointer is never created, so the client dereferences null and dies. "basic" is fine. It is only the "all" level, because that is the one that prints the XA2 line.
Environment
DayZDiag_x64.exe 1.30.164.200 (RPT header: Version 1.30.164200.56), windowed client connected to a local diag server
Windows 11 26H2 (build 26300) in a Hyper-V Gen2 VM with the GPU passed through (GPU-PV, NVIDIA)
The VM has no sound device at all: no Win32_SoundDevice, no AudioEndpoint devices. Audiosrv and AudioEndpointBuilder are running. The client logs nothing about missing audio and otherwise runs fine.
Mods were loaded. No script is involved in the crash (see below), but I haven't tried a vanilla-only launch yet.
From the RPT:
21:42:56.320 ENGINE (F): Crashed
Exception code: C0000005 ACCESS_VIOLATION at 697F4540
Fault address: 697F4540 00:697F4540 Unknown module
Prev. code bytes: EB 02 33 C9 48 8B 89 A0 00 00 00 48 8D 54 24 40
Fault code bytes: 48 8B 01 FF 50 70 8B 44 24 74 4C 8D 05 2F 36 BB
The RPT says "Unknown module", but Windows Error Reporting puts the fault inside the exe itself: faulting module DayZDiag_x64.exe 1.30.164.200 (timestamp 0x6acdf10e), exception 0xc0000005, fault offset 0x00000000008e4540.
Error in DayZDiag 1.30.164.200 is around RVA 0x8E4540 (image base 0x140000000). The function starts at RVA 0x8E44F0:
0x8E4520 mov rax, [rip+...] ; global at RVA 0x4F12800 - the audio engine object
0x8E4527 test rax, rax
0x8E452A je 0x8E4532
0x8E452C lea rcx, [rax-10h]
0x8E4530 jmp 0x8E4534
0x8E4532 xor ecx, ecx
0x8E4534 mov rcx, [rcx+0A0h] ; XAudio2 interface pointer - NULL when there is no audio device
0x8E453B lea rdx, [rsp+40h] ; a 0x40-byte stack struct, zeroed at the start of the function
0x8E4540 mov rax, [rcx] ; <-- crash: rcx = 0
0x8E4543 call qword ptr [rax+70h] ; vtable slot 14 = IXAudio2 (2.7) ::GetPerformanceData
0x8E454A lea r8, "XA2: Active sourceVoices: %d | Total sourceVoices: %d | submixVoices: %d | re-sa..."
... (then reads +0x24, +0x28, +0x2C, +0x30, +0x34 of that struct and formats the line)
So the code already copes with the audio engine object itself being null (the test/je/xor). It never checks the XAudio2 pointer it loads from +0xA0 before calling through it. Slot 14 (0x70) in the IXAudio2 2.7 vtable is GetPerformanceData.
Suggested fix
Null check the XAudio2 pointer before the call
IXAudio2* xa = audio ? audio->m_XAudio2 : nullptr;
if (xa)
{
//call GetPerformanceData and stuff
}