How to uninstall the non-stop (continue on floating-point exceptions) mode?

Viewed 55

C11, 7.6.4.2 The feholdexcept function, Description, 2 (emphasis added):

The feholdexcept function saves the current floating-point environment in the object pointed to by envp, clears the floating-point status flags, and then installs a non-stop (continue on floating-point exceptions) mode, if available, for all floating-point exceptions.218

Footnote 218:

IEC 60559 systems have a default non-stop mode, and typically at least one other mode for trap handling or aborting; if the system provides only the non-stop mode then installing it is trivial. For such systems, the feholdexcept function can be used in conjunction with the feupdateenv function to write routines that hide spurious floating-point exceptions from their callers

A simple question: How to uninstall the non-stop (continue on floating-point exceptions) mode?


UPD20220725. Got an answer from Fred J. Tydeman (Vice-chair of PL22.11 (ANSI "C")):

Standard C does not provide any way to do that.

Hence, it may be a defect. To be continued.

1 Answers

How to uninstall the non-stop (continue on floating-point exceptions) mode?

You can call the feupdateenv function, passing it the address of the environment object saved when you (last) called feholdexcept:

#include <fenv.h>

double foo(double arg)
{
    fenv_t saved_mode;
    feholdexcept(&saved_mode);
    double result = arg;
    // do stuff ...

    feupdateenv(&saved_mode); // restore
    return result;
}

Alternatively, if you don't want to "remember the currently raised exceptions" and then (re-)raise them after the restoration, you can call the fsetenv function to restore the saved environment, instead.


Note: On the issue raised (in the comments) on whether or not a call to either feupdateenv or fsetenv (with a pointer to an appropriate saved environment) will actually uninstall the "non-stop" (continue on FP exceptions) mode, the cppreference page for feholdexcept has this to say (bold emphasis my own):

First, saves the current floating-point environment to the object pointed to by envp (similar to fegetenv), then clears all floating-point status flags, and then installs the non-stop mode: future floating-point exceptions will not interrupt execution (will not trap), until the floating-point environment is restored by feupdateenv or fesetenv.

However, this question is tagged and, although the cppreference website is a reliable – and largely accurate – source (for both C++ and C), it is not the C Standard and should not be used in lieu of that. So, I searched for a similar note in this C11 Draft Standard, but failed to find one.

The best 'confirmation' I could find is the example given in that draft, in the section on the feupdateenv function (§7.6.4.4):

EXAMPLE Hide spurious underflow floating-point exceptions:

#include <fenv.h>
double f(double x)
{
    #pragma STDC FENV_ACCESS ON
    double result;
    fenv_t save_env;
    if (feholdexcept(&save_env))
        return /* indication of an environmental problem */;
    // compute result
    if (/* test spurious underflow */)
        if (feclearexcept(FE_UNDERFLOW))
            return /* indication of an environmental problem */;
    if (feupdateenv(&save_env))
        return /* indication of an environmental problem */;
    return result;
}

I read that example as implicitly indicating that the FP exception mode is fully restored to its saved value by a successful call to feupdateenv.

Related