0XC000008D

Fix 0xC000008D STATUS_FLOAT_DENORMAL_OPERAND Crash

That 0xC000008D crash means your CPU choked on a denormal float. Here's how to stop it — usually via FTZ/DAZ or a compiler flag.

So your app just blew up with 0xC000008D and you've got a stack trace that points somewhere useless. Yeah, that's annoying. Let's kill it.

The fast fix

Denormal exceptions are almost always caused by the FPU control word or MXCSR register being set to trap on denormals — which is not the default, but legacy code, badly ported x87 code, or a specific library can flip it. The fix is to tell the CPU to silently flush denormals to zero instead of throwing.

If you control the source, drop this at the top of your entry point:

#include <float.h>

int main() {
    // Clear the denormal exception flag and set flush-to-zero behavior
    _controlfp_s(NULL, _DN_FLUSH, _MCW_DN);
    // ... your app
}

On MSVC, _controlfp_s(NULL, _DN_FLUSH, _MCW_DN) masks the denormal operand exception and enables flush behavior for both x87 and SSE. That single call fixes it in 90% of cases.

If you're on GCC or Clang, use the compiler intrinsic instead:

#include <xmmintrin.h>
#include <pmmintrin.h>

int main() {
    _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
    _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
    // rest of app
}

That sets FTZ and DAZ bits in MXCSR for SSE. If your code mixes x87 and SSE — and a lot of old numeric code does — you need both. The x87 control word and MXCSR are separate registers. Don't assume setting one handles the other.

Why that works

IEEE 754 defines denormals as tiny numbers near zero that lose precision but keep gradual underflow working. Most CPUs handle them silently. But the exception is available because some math is sensitive to the precision loss, and some workloads would rather know than get a slightly wrong answer.

When the denormal operand trap is enabled, any operation involving a denormal raises an exception. On Windows that gets mapped to a structured exception with code 0xC000008D. Your process either crashes or, if you've got an SEH handler, gets handed the exception and probably does something dumb with it.

Flushing denormals to zero means the operation produces zero instead of throwing. For 99% of software this is fine — signal processing, game physics, graphics, machine learning all do this by default because denormals tank performance anyway. On some CPUs denormal math is 10-100x slower than normal math. Intel specifically has had this problem on every generation since Pentium 4.

So flushing is both a correctness fix for the crash and a performance fix. Two birds.

When the fast fix doesn't work

Three scenarios where the above isn't enough.

1. The exception is being raised inside a DLL you don't control

A third-party library — DirectX, CUDA runtime, an old math kernel — is setting the control word itself. You call _controlfp_s at startup, then the library stomps on it. Usually it happens during init. The trick is to also hook the exception handler so you can identify who's flipping the bit:

LONG WINAPI DenormalHandler(PEXCEPTION_POINTERS p) {
    if (p->ExceptionRecord->ExceptionCode == 0xC000008D) {
        // Log, inspect, or just swallow it
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    return EXCEPTION_CONTINUE_SEARCH;
}

Register with AddVectoredExceptionHandler(1, DenormalHandler) so you run before SEH. Swallow the exception, let the operation continue, and move on. Not elegant. Works.

2. Compiler flags are re-enabling the trap

MSVC's /fp:strict and /fp:precise can re-enable denormal traps in certain build configurations depending on which CRT you link against. GCC's -ftrapping-math does the same. Check your build flags. If you see -ftrapping-math or /fp:strict, that's a suspect.

The pragmatic fix: compile with /fp:fast on MSVC or -ffast-math on GCC/Clang. These set FTZ/DAZ implicitly and disable denormal traps. Yes, -ffast-math changes numerical behavior and can break code that depends on strict IEEE semantics. If you're doing financial math or anything that needs reproducible results, don't use it. For everything else, it's fine.

3. Mixed SSE/AVX code with different MXCSR settings

AVX has its own MXCSR context. If you set FTZ in one thread and spawn a worker, the worker thread has its own control word. Set the flags per-thread.

void InitThreadFloat() {
    _controlfp_s(NULL, _DN_FLUSH, _MCW_DN);
    _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
    _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
}

// Call InitThreadFloat() at the top of every thread entry point

Threadpools, OpenMP regions, std::async — all of them need this if they're doing float math.

Don't do this

Don't try to fix this by rewriting the math to avoid denormals. You'll chase ghosts for weeks. The hardware and OS give you a clean way to opt out of the trap. Use it.

Also don't disable the whole FPU exception mask (_MCW_EM) blindly. That masks divide-by-zero and invalid-operand exceptions too, and now you've got silent NaNs propagating through your pipeline. Mask only the denormal exception.

Prevention

Set FTZ/DAZ at process startup and at every thread entry point, before any float math runs. Wrap it in a helper and call it everywhere. Add a one-line comment explaining why — future you will thank present you when the next denormal bug shows up.

If you're shipping a library, document whether you expect the caller to have denormal flushing on. Half the crashes I've seen with this code trace back to a library assuming it was set and the host app not setting it.

And if you're seeing 0xC000008D intermittently — always under load, never on the dev box — that's the classic signature of denormals appearing only in specific data. Audio processing with very quiet passages, ML with near-zero gradients, physics sim with objects nearly at rest. The flush fix handles all of these. Ship it.

Related Errors in Programming & Dev Tools
java.lang.OutOfMemoryError: Java heap space Fixing Java OutOfMemoryError: Java heap space TypeError: Failed to execute 'eval' on 'Window': This document requires 'Trusted Trusted Types blocking eval(): the real fix Module parse failed Webpack 5 Vue: Module parse failed Unexpected token fix 0XC0000025 STATUS_NONCONTINUABLE_EXCEPTION 0xC0000025 on Windows

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.