Feholdexcept In C++ - C++ Programming Tutorial
C++ Course / Miscellaneous / Feholdexcept In C++

Feholdexcept In C++

BLUF: Mastering Feholdexcept In C++ is a critical step in becoming a proficient C++ developer. This lesson provides a deep dive into the syntax, performance considerations, and real-world applications of this concept.
Key Performance Insight: Feholdexcept In C++

C++ is renowned for its efficiency. Learn how Feholdexcept In C++ enables low-level control and high-performance computing in the tutorial below.

Floating-point computations in software are frequently subject to approximations that can result in inaccuracies and exceptional scenarios. These anomalies have the potential to trigger unintended program termination or produce incorrect results, particularly during precise numerical computations. C++ offers tools to manage these floating-point exceptions and features functions that allow for the temporary suspension of exception handling as required.

One notable method for managing floating-point exceptions is the feholdexcept function. This specific function enables the retention of the existing floating-point setting, resetting the flags to disable exceptions temporarily while executing code and then reinstating the setting afterward. By segmenting segments of code that could potentially trigger unexpected exceptions, a software application can be enhanced in resilience and error-handling capabilities.

The feholdexcept Function is defined in the <fenv.h> header and enables the preservation and resetting of specific floating point exception flags as indicated by its fenvt environment parameter. Once the critical code has been run with exceptions turned off, the initial environment can be reinstated using fenvsetenv. This guide elaborates on the feholdexcept Function, illustrates its application, and underscores its significance in handling numerical exceptions.

By grasping concepts such as feholdexcept, programmers can segregate unreliable numerical computations in their C++ applications while upholding exception-handling mechanisms in other parts. This facilitates the creation of accurate and resilient code that prevents abrupt terminations caused by inevitable floating-point imprecisions.

What is feholdexcept function :

The feholdexcept function allows for the preservation and resetting of the current floating-point environment to temporarily disable floating-point exceptions. Its syntax in C++ is as follows:

fenvt feholdexcept(fenvt env);

It accepts a single parameter, env, along with an fenvt structure to retain the current state. fenvt is a data type specified in <fenv.h> that encapsulates the complete floating-point environment.

Within the feholdexcept function, the existing exception flags are stored in the env parameter. These flags serve as indicators for when a floating-point exception is triggered, such as an invalid operation, division by zero, overflow, or any other numerical issue.

The available floating-point exceptions are:

  • FE_DIVBYZERO - Divide by zero
  • FE_INEXACT - Inexact result
  • FE_INVALID - Invalid operation
  • FE_OVERFLOW - Numeric overflow
  • FE_UNDERFLOW - Numeric underflow

After saving the current flags, the feholdexcept function resets the designated exception flags that are provided to it. Normally, FEALLEXCEPT is passed to reset all flags simultaneously for a temporary period.

With the flags reset, any code within the safeguarded area will not trigger exceptions, even for mathematically incorrect operations. The prior state of the environment saved in the env can be brought back later by invoking fenv_setenv, which will bring back the flags. This segregates code segments that require lenient treatment while upholding stringent behavior in all other parts.

In simple terms, feholdexcept enables the disabling of exception triggers within a specific code section, granting the ability to specify where numeric exceptions are managed within a C++ application. This function aids in enhancing the control of floating-point operations.

Uses of the feholdexcept function:

  • Temporarily turn off floating-point exceptions in sensitive numerical code: Call feholdexcept before code sections that may undesirably throw exceptions due to unavoidable inaccuracies. It prevents unwanted program termination.
  • Isolate buggy floating point code: Use feholdexcept/fenv_setenv around code you suspect contains numerical bugs to allow execution. The later correction will then enable exceptions again for that code.
  • Improve computational performance: Exception handling can reduce the speed of math-intensive programs. feholdexcept effectively turns off this handling in non-critical sections to improve speed.
  • Let iterative calculations continue: Certain algorithms may hit occasional exceptions but produce usable interim results. Wrapping iterations in feholdexcept allows completion rather than early termination.
  • Maintain surrounding exception behaviour: By only clearing flags locally, code external to the feholdexcept protected section will keep behaving regularly and throw exceptions when warranted.
  • Implement custom floating point exception handling: Save and restore the environment around sections of custom exception handling code rather than using C++ default mechanisms.
  • Gradually enable exceptions: When migrating or testing floating point code, temporarily use feholdexcept, and then "shrink" its scope to fix and expose issues incrementally.
  • Reduce debugging complexity: Disable exceptions in some code during debugging to independently simplify the analysis of known numeric issue sections.
  • Implementation of the feholdexcept function:

Let's consider a C++ program to demonstrate the feholdexcept function.

Example

#include <iostream>
#include <cfenv>
#include <cmath>

double safeDivision(double dividend, double divisor) {
// Save the current floating-point environment
fenv_t currentEnv;
fegetenv(�tEnv);

// Perform the division operation
double result = dividend / divisor;

// Use feholdexcept to clear exceptions
fenv_t newEnv;
feholdexcept(&newEnv);

// Clear specific exceptions that might have occurred
feclearexcept(FE_OVERFLOW | FE_DIVBYZERO);

return result;
}

int main() {
// Clear all floating-point exceptions
feclearexcept(FE_ALL_EXCEPT);

double numerator = 10;
double denominator = 0;

// Get the result of the division and handle exceptions
double divisionResult = safeDivision(numerator, denominator);

// Print the division result
std::cout << "Result of division: " << divisionResult << std::endl;

// Check for exceptions after the division
if (!fetestexcept(FE_ALL_EXCEPT)) {
std::cout << "No exceptions raised during division" << std::endl;
}

return 0;
}

Output:

Output

Result of division: inf
No exceptions raised during division.

Explanation:

  • Include the necessary headers: iostream: It is used for input/output stream functionality cfenv: It is used for floating-point environment functions like feholdexcept cmath: It contains various math functions.
  • Define a safeDivision function that takes two doubles as arguments (dividend and divisor) and returns their division result as a double.
  • Inside safeDivision: Declare a fenv_t object called currentEnv to save the current floating-point environment. b. Call fegetenv and pass the address of currentEnv. It saves the current floating-point state into currentEnv.
  • Perform the actual division operation between the passed arguments and store the result.
  • Declare another fenv_t object called newEnv . It will be used with feholdexcept.
  • Call feholdexcept, passing the address of newEnv . It saves the current environment into newEnv and clears the flags.
  • Explicitly clear the overflow and divide-by-zero flags using feclearexcept. It is done because the previous environment stored in newEnv may have had these flags set from earlier operations. We want a clean environment inside this Function.
  • Return the division result. At this point, any floating-point exceptions during the division would not generate exceptions due to the cleared environment.
  • In main function:
  • Clear all floating point exception flags using feclearexcept.
  • Define the dividend and divisor values. The divisor is set to 0 to cause a divide-by-zero.
  • Call safeDivision , which returns the result.
  • Print out the result.
  • Use fetestexcept to check if any exceptions were raised during safeDivision. f. Print out an appropriate message based on the previous step.
  • iostream: It is used for input/output stream functionality
  • cfenv: It is used for floating-point environment functions like feholdexcept
  • cmath: It contains various math functions.
  • Program 2:

Let's consider another C++ program to demonstrate the feholdexcept function.

Example

#include <iostream>
#include <cfenv>
using namespace std;

//Function to display raised exceptions
void displayExceptions()
{
cout << "Exceptions raised: ";

if (fetestexcept(FE_DIVBYZERO))
cout << "FE_DIVBYZERO\n";
else if (fetestexcept(FE_INVALID))
cout << "FE_INVALID\n";
else if (fetestexcept(FE_OVERFLOW))
cout << "FE_OVERFLOW\n";
else if (fetestexcept(FE_UNDERFLOW))
cout << "FE_UNDERFLOW\n";
else
cout << "No exceptions found\n";
}

// Driver code
int main()
{
// Current floating-point environment
fenv_t currentEnvironment;

// Raising specific exceptions (FE_DIVBYZERO)
feraiseexcept(FE_DIVBYZERO);

// Displaying raised exceptions
displayExceptions();

// Saving and clearing current exceptions with feholdexcept()
fenv_t newEnvironment;
feholdexcept(&newEnvironment);

// Checking for exceptions after feholdexcept()
displayExceptions();

// Restoring previously saved exceptions
feupdateenv(&newEnvironment);

// Displaying exceptions after restoration
displayExceptions();

return 0;
}

Output:

Output

Exceptions raised: FE_DIVBYZERO
Exceptions raised: No exceptions found
Exceptions raised: FE_DIVBYZERO

Explanation:

  • Include necessary headers - iostream for I/O, cfenv for floating point environment functions
  • Define a displayExceptions Function to print any currently raised floating-point exceptions using fetestexcept
  • In the main function:
  • Declare a fenv_t object called current environment to hold the environment
  • Explicitly raise a "divide by zero" exception using feraiseexcept to simulate an error
  • Call displayExceptions first time to print the raised exception
  • Declare another fenv_t object called newEnvironment
  • Call feholdexcept, passing address of newEnvironment. This will: Save the current environment with flags into newEnvironment Clear the flags in the current environment
  • Call displayExceptions This time, it will not show any raised exceptions due to step 8.
  • Restore the saved environment in newEnvironment back into the current environment using feupdateenv
  • Call displayExceptions third time, now showing "FE_DIVBYZERO" exception again since restored
  • Save the current environment with flags into newEnvironment
  • Clear the flags in the current environment

In summary:

  • Raised an exception.
  • Used feholdexcept to save and clean the environment
  • After that, the code was executed with no raised exceptions.
  • Finally, restored the original environment using a pointer, bringing back the exception, too.

It showcases the functionality of feholdexcept in temporarily deactivating and then reactivating exception handling as required.

Conclusion:

The feholdexcept function offers C++ programmers precise control over how floating point exceptions are handled during numerical computations. This function allows developers to temporarily disable exceptions during critical calculations by clearing flags and then restoring the original state using fenv_setenv. This strategy helps prevent abrupt termination of the code and enables it to continue running smoothly. By containing these exceptions within specific sections of the code, developers can maintain strict behavior in unaffected areas. Essentially, feholdexcept and its counterparts empower developers to effectively manage floating point inaccuracies and exceptions, ensuring the development of accurate and resilient numerical algorithms. Leveraging these mechanisms enables programmers to create robust and reliable C++ applications that can handle computational challenges effectively.

Input Required

This code uses input(). Please provide values below:

Logic Practice
Install Logic Practice
Add to home screen for a faster app-like experience