|
Home > Archive > Unix Programming > October 2004 > Signal Call
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
|
|
| Amit Sharma 2004-10-02, 9:13 pm |
| Hi,
I want to write a program, where until we give the value of j as
non zero, it should go on asking us values of i and j, displaying the
message "Division by zero: Floating point exception" for every input
of j as zero. Once we give the value of both i and j as non-zero, it
displays i/j and terminates.
This is the sample code i tried:
#include <signal.h>
#include <stdio.h>
#inclue <stdlib.h>
void sig_s(int signo);
void Divide();
void main( )
{
signal(SIGFPE,sig_s);
Divide();
}
void Divide()
{
int i,j,k;
printf("Enter a number\n");
scanf("%d",&i);
printf("another number\n");
scanf("%d",&j);
if( (i==0) && (j==0))
{
printf("Total is %d\n",0);
exit(0);
}
else
{
printf("Total is %d\n",i/j);
}
}
void sig_s(int signo)
{
signal(SIGFPE,sig_s);
printf("Division by zero:Floating point exception\n");
Divide();
}
It works fine as you give the denominator as zero and ask for the new
number but if you give the valid values also (e.g. i=10, j=5) Then
also it went into the Signal handler function and call the signal
handler recursively.
Could you please suggest me how i can acheive this ??
Thanks,
Amit
| |
| Pascal Bourguignon 2004-10-02, 9:13 pm |
| sharma.am@gmail.com (Amit Sharma) writes:
> Hi,
> I want to write a program, where until we give the value of j as
> non zero, it should go on asking us values of i and j, displaying the
> message "Division by zero: Floating point exception" for every input
> of j as zero. Once we give the value of both i and j as non-zero, it
> displays i/j and terminates.
>
> This is the sample code i tried:
> #include <signal.h>
> #include <stdio.h>
> #inclue <stdlib.h>
>
> void sig_s(int signo);
> void Divide();
>
> void main( )
> {
> signal(SIGFPE,sig_s);
> Divide();
>
> }
> void Divide()
> {
> int i,j,k;
> printf("Enter a number\n");
> scanf("%d",&i);
> printf("another number\n");
> scanf("%d",&j);
> if( (i==0) && (j==0))
> {
> printf("Total is %d\n",0);
Big bug here! 0/0 is undefined.
sin x
For example, lim ------- = 1, not 0.
x->0 x
> exit(0);
> }
> else
> {
> printf("Total is %d\n",i/j);
> }
> }
>
> void sig_s(int signo)
> {
> signal(SIGFPE,sig_s);
> printf("Division by zero:Floating point exception\n");
> Divide();
> }
>
> It works fine as you give the denominator as zero and ask for the new
> number but if you give the valid values also (e.g. i=10, j=5) Then
> also it went into the Signal handler function and call the signal
> handler recursively.
> Could you please suggest me how i can acheive this ??
By not calling Divide recursively in the signal handler!
Very little can and should be done in a signal handler.
For example, a printf is out of question here.
The best way, is to always test for a null denominator before every
division (or prove your pre-conditions!).
For example, instead of writting:
printf("another number\n");
scanf("%d",&j);
you should write:
do{
printf("please enter a denominator (non-null integer):\n");
scanf("%d",&j);
if(j==0){
printf("Invalid denominator. Try again.\n");
}
}while(j==0);
Now, if you really want to trap SIGFPE, you should read this:
According to POSIX, the behaviour of a process is undefined after
it ignores a SIGFPE, SIGILL, or SIGSEGV signal that was not gen_
erated by the kill(2) or the raise(3) functions. Integer divi_
sion by zero has undefined result. On some architectures it will
generate a SIGFPE signal. (Also dividing the most negative inte_
ger by -1 may generate SIGFPE.) Ignoring this signal might lead
to an endless loop.
That means that one cannot return from a SIG_FPE signal handler with
the hope of returning to the instructions after the divide. Indeed,
on Linux 2.4, even when signal(SIGFPE,SIG_IGN); in the handler,
returning the handler will retry the division. On some system, you
could hack the trap, see for example:
http://publib16.boulder.ibm.com/pse...oint_except.htm
but this is not portable. The best bet to handle SIG_FPE is to use
longjmp. But remember that on some systems, 1/0 may return MAX_INT
without exception.
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
static jmp_buf divide_by_zero_jmp;
static void sig_s(int signo){
signal(SIGFPE,sig_s);
longjmp(divide_by_zero_jmp,1);
}
static void divide(void){
int i,j,k;
if(setjmp(divide_by_zero_jmp)){
printf("Division by zero: Floating point exception.\n");
}
for(;;){
printf("Enter a numerator: ");
fflush(stdout);
scanf("%d",&i);
printf("Enter a denominator (non null): ");
fflush(stdout);
scanf("%d",&j);
if((i==0)&&(j==0)){
printf("Quotient undefined.\n");
fflush(stdout);
}else{
k=i/j;
printf("Quotient is %d\n",k);
fflush(stdout);
break;
}}}
int main(void){
signal(SIGFPE,sig_s);
divide();
return(0);
}
$ ./a
Enter a numerator: -2147483648 ||
Enter a denominator (non null): -1 || !!!
Division by zero: Floating point exception. ||
Enter a numerator: -1
Enter a denominator (non null): 0
Division by zero: Floating point exception.
Enter a numerator: 1
Enter a denominator (non null): -1
Quotient is -1
--
__Pascal Bourguignon__ http://www.informatimago.com/
Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we.
|
|
|
|
|