5

errno is not being set to EDOM for domain error of sqrt() function in windows It shows correctly on Linux but failed on windows (Using GCC 7.4) ...

#include <stdio.h>
#include <errno.h>
#include <math.h>

int main () {
double val;

errno = 0;
val = sqrt(-10);

if(errno == EDOM) {
printf("Invalid value \n");
} else {
printf("Valid value\n");
} 

errno = 0;
val = sqrt(10);

if(errno == EDOM) {
printf("Invalid value\n");
} else {
printf("Valid value\n");
}

return(0);
}

Expected result : Invalid value Valid value Actual result : Valid value Valid value

Tilak_Chad
  • 111
  • 3
  • 1
    You really don't want floating-point math functions to set `errno`. It's a bad idea and only kept for compatibility with legacy crap. Without it, code generation for modern architectures is much nicer, since the compiler can just use the `sqrt` instruction of the underlying hardware (causing the somewhat more sane ieee754 exception flag to be set on invalid operands), whereas it needs to emit extra code to set `errno` (which no sane programmer will use), so there is a compiler flag `-fno-math-errno` to get sane behavior. – EOF May 21 '19 at 18:06

2 Answers2

8

The math functions are not required to set errno. They might, but they don't have to. See section 7.12.1 of the C standard. Theoretically you can inspect the value of the global constant math_errhandling to find out whether they will, but that's not fully reliable on any implementation I know of, and may not even be defined (it's a macro, so you can at least use #ifdef to check for it).

Instead, you can check whether the input is negative before calling sqrt, or (if your implementation properly supports IEEE 754 in detail) you can check whether the output is NaN (using isnan) afterward.

zwol
  • 135,547
  • 38
  • 252
  • 361
4

As @zwol observed, the Standard allows implementations some latitude with respect to how (and whether) the math functions signal errors. In particular:

On a domain error, the function returns an implementation-defined value; if the integer expression math_errhandling & MATH_ERRNO is nonzero, the integer expression errno acquires the value EDOM; if the integer expression math_errhandling & MATH_ERREXCEPT is nonzero, the ''invalid'' floating-point exception is raised.

(C11, paragraph 7.12.1/2)

Upon a domain error in sqrt,

  • On Linux with glibc, NaN is returned, errno is set to EDOM, and a floating-point exception is raised.

  • On Windows with recent MS runtime library, an indefinite NaN is returned, and a floating-point exception is raised, maybe (the docs are a bit unclear to me, but definitely some kind of status flag is set that you can subsequently evaluate via the _matherr() function). There is no mention of setting errno.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157