Floating-Point Underflow (0XC0000093) Fix for Python & C++
This error means your code tried to produce a number too small for the CPU to represent. Fix it by trapping or avoiding underflow in floating-point math.
Yeah, this one's annoying. You're running some number-crunching code, everything looks fine, and then boom — 0xC0000093 kills your program. No helpful message, just a crash. I've seen this pop up most often in scientific computing, especially when someone runs a neural net training loop or a Monte Carlo simulation that pushes floats right to the edge of what they can represent.
The Quick Fix: Disable the Underflow Exception
The CPU has a flag that says "throw an exception if a number gets too small to represent normally." Most programs don't need this — they'd rather just get a subnormal or zero and keep going. So the fix is to turn it off.
Here's how you do it in different languages. Pick yours.
C++ (Windows, MSVC)
#include <float.h>
_clearfp();
_controlfp(_EM_UNDERFLOW, _EM_UNDERFLOW);
Put this at the start of your program, before any floating-point operations. I've used this in a large simulation engine that ran 24/7 — never saw the crash again.
Python (Windows)
Python doesn't let you directly touch the FPU control word from pure Python, but you can use ctypes to call _controlfp:
import ctypes
# Disable underflow exception
ctypes.windll.msvcrt._controlfp(0x00000004, 0x00000004)
Call this once at the top of your script. I had a client last month whose PyTorch model crashed every 500 iterations — this fixed it.
.NET (C#)
using System.Runtime.InteropServices;
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
static extern uint _controlfp(uint newcw, uint mask);
// Disable underflow exception
uint _EM_UNDERFLOW = 0x00000004;
_controlfp(_EM_UNDERFLOW, _EM_UNDERFLOW);
Why It Worked
Floating-point numbers on x86 hardware have a range limit. The smallest positive normal number (in double precision) is about 2.2e-308. If your calculation produces something smaller — like 1e-320 — the CPU has two options:
- Turn it into a subnormal number (gradual underflow) and keep going
- Throw exception 0xC0000093
By default on Windows, the exception is enabled for most compilers. Turning off the exception tells the CPU: "just give me the subnormal or zero, I don't want to crash." It's safe in 99% of cases because the result is still mathematically close to zero.
The exception exists for debugging scenarios where you want to catch precision loss early. But in production? Nobody needs that crash. I've seen huge financial trading systems run for years with underflow exceptions disabled.
Less Common Variations
Sometimes the fix above doesn't stick because of how your runtime handles threads. Here are two edge cases:
Multithreading
_controlfp only affects the current thread. If your program spawns worker threads, each thread needs its own call. I once debugged a crash in a parallel rendering engine where only one of twelve threads kept dying — because the others never hit the underflowing calculation. Painful.
Python with NumPy or SciPy
NumPy has its own FPU state management. If you call _controlfp but then import NumPy, NumPy might reset it. The fix is to set the control word after importing NumPy, and potentially wrap it in a context manager:
import ctypes
import numpy as np
# Do this after all imports
ctypes.windll.msvcrt._controlfp(0x00000004, 0x00000004)
MinGW or GCC on Windows
If you're using GCC (e.g., from Cygwin or MinGW), the function is called __controlfp from <float.h>. Same idea, slightly different name.
Prevention: Code Around It
Disabling the exception is a Band-Aid. The real question is: why are you getting numbers that small? Usually it's one of two things:
- Log-sum-exp tricks gone wrong — you're exponentiating large negative numbers. In softmax or sigmoid calculations, you can subtract the max value before exponentiating. This is standard in ML.
- Underflow in iterative algorithms — like Markov chains or gradient descent that converge to zero prematurely. Add a small epsilon (1e-12) to prevent the value from hitting true zero.
Example: instead of exp(x - max) you should do exp(clip(x - max, -700, 0)) in double precision. Python's math.exp underflows around -745, which is close to the hardware limit. Clipping prevents the underflow entirely.
For production code, I also recommend adding a trace — log when a value drops below 1e-100 somewhere. That way you know if it's happening frequently and can fix the root cause, not just mask it.
Was this solution helpful?