INF: Must Use Parentheses with _fpreset()

ID Number: Q66149

6.00 6.00a 6.00ax 7.00 | 6.00 6.00a

MS-DOS | OS/2

Summary:

In Microsoft C versions 6.0, 6.0a, 6.0ax, and C/C++ version 7.0, when

using the signal() function, it is necessary to call the _fpreset()

function before calling longjmp() within the function referenced by

signal(). If you do not do this, the program will give unpredictable

results. In the program example below, due to user error, the loop is

executed twelve times, then a pointer gets lost (caused by longjmp)

and proceeds to hang the machine (under OS/2 you will get a protection

violation) because the _fpreset function doesn't have parentheses

after it.

More Information:

Even though "_fpreset" is stated within the fperror() function in the

code example below, it is evaluated only as an expression rather than

a function because the parentheses required to call a function are not

included in the statement [for example, "_fpreset()"]. Therefore,

_fpreset is evaluated but no value is assigned to it, which gives it

the characteristics of an assembly language NOP instruction.

If you compile this code with the default warning level, there won't

be any warnings or indications of error, so you might think the

compiler is generating incorrect code; in fact, if you compile the

code on warning level 4 (/W4), you will get "warning C4205: statement

has no effect", which indicates that the _fpreset will have no effect,

or in other words, is going to do nothing.

Sample Code

-----------

/* Compile options needed: <none>

*/

#include <signal.h>

#include <setjmp.h>

#include <conio.h>

#include <stdio.h>

#include <float.h>

void fperror(int sig, int num);

jmp_buf mark;

double val, d;

int fpe, st, k;

void main(void)

{

d=0;

signal (SIGFPE, fperror);

while(!kbhit())

{

val=100;

st=0;

fpe=setjmp(mark);

if(fpe==0)

{

printf("BEFORE /0 st = %-4d k = %-5d\n", st, k++);

val=val/d;

printf("NOERR val = %f st = %-4d\n", val, st);

}

else

{

printf("FPERROR val = %f st = %-4d\n", val, st);

}

}

}

void fperror(int sig, int num)

{

_fpreset; /* should be "_fpreset()" */

st=1;

longjmp(mark,-1);

}

Additional reference words: 6.00 6.00a 6.00ax 7.00