2009-07-21 2 views
0

SIGFPE의 신호 처리기에서 돌아 왔을 때, 변수 i는 내 프로그램에서 올바른 결과를 얻으려는 것보다 하나가 작습니다 (모든 것을 반복합니다). 쌍 배열의 쌍) 신호 "catch"에서 돌아 오는 경우 sigsetjmp의 반환 값을 확인하고 i를 증가시켜야합니다. 왜 이런거야? 부동 소수점 예외의 반복 과정에서 발생하는 증분이 손실되는 이유는 무엇입니까?리눅스에서 C가있는 sigsetjmp의 모호한 문제

#include <stdio.h> 
#include <signal.h> 
#include <stdlib.h> 
#include <setjmp.h>                

jmp_buf e; 

int i; 
void float_exception(); 
int main() 
{ 
    int pairs[][2] = { 
     {10, -5}, {10, -3}, {-10, -3}, {-10, -5}, {-10, 3}, {-10, 5}, {-10, 0}, 
     {10, 0}, {0, 10}, {2, 3}, {3, 3}, {5, 10} 
    }; 
    int npairs; 
    /* handle sigfpe so /0 doesn't interrupt the rest of the program */ 
    signal (SIGFPE, float_exception); 
    printf ("Seeing what my C implementation does with negative or 0 modulo" 
      "\narithmetic.\n"); 
    npairs = sizeof (pairs)/sizeof (int)/2; 
    i = 0; 

    if (sigsetjmp (e, 1) != 0) { 
     i++; /* without this line, i is one less than I expect it to be */ 
    } 
    for (; i < npairs - 1; i++) { 
     printf ("%d: %d %% %d\t= ", i, pairs[i][0], pairs[i][1]); 
     fflush (stdout); 
     printf ("%d\n", pairs[i][0] %pairs[i][1]); 
     fflush (stdout); 
    } 
    return 0; 
} 



void float_exception() 
{ 
    printf ("fpe\n"); 
    fflush (stdout); 
    longjmp (e, 1); 
} 

답변

0

카페 답이 옳은 것 같습니다.

처음에 실제로 기대했던 것은 휘발성이라고 선언해야했습니다. 적어도 그것은 NSBlog claims의 저자입니다.

참고 사항 : 신호 처리기 내에서 printf 및 fflush를 호출하려면 dangerous 일 수 있습니다. SIGFPE가 동기식 신호라는 사실을 감안할 때, 완전히 의문의 여지가 없지만 자신이하는 일을 알아야합니다.

마지막으로 Linux man 페이지에서 : "longjmp() 및 siglongjmp()는 프로그램을 이해하고 유지 관리하기 어렵게 만듭니다. 가능한 경우 대안을 사용해야합니다."

+0

나는 아무 소용 내가 휘발성를 선언 시도했다, 나는 카페의 대답은 바로 너무 생각입니다. 긴/sigset/JMP 내가 찾을 수있는 유일한 일이었다 나를 콜백 함수에서 뛰어 내리고 루프로 돌아 가게 할 것입니다. 그렇지 않으면 예외가 계속 반복해서 신호를 계속 방출합니다 (0으로 나누기 때문에 정말 놀랍지는 않습니다). 그리고 그 루프에서 벗어나기 위해서 저는 신호 처리기에서 다른 코드 블록으로 이동할 필요가있다. float_execption() stdio 주위에 뮤텍스를 사용할 수있을 것 같아요. –

+0

신호 처리기 내에서 signal()을 제외한 * 모든 * 라이브러리 함수를 호출하는 것은 위험합니다. 우리가 신호 처리기에서 printf()를 호출했지만 콘솔에 메시지를 쓰는 대신 부분적으로 o를 덮어 썼습니다. f. 우리가 업데이트 한 Access .mdb 파일. 복구 할 수 없을 정도로 데이터베이스가 손상되었습니다. 솔직히 C는 이와 같은 예외 처리에 아주 좋은 도구를 제공하지 않습니다. 작업을 시도하기 전에 인수에 대한 온 전성 검사를하는 것이 훨씬 낫습니다. –

+0

@Ringding, 0으로 나눈 값은 정의되지 않은 동작이므로 Tom은 신호가 발생한다는 것을 전혀 보증하지 않습니다 (C 표준에 의해 제공됨, POSIX 표준은 보장 할 수는 없지만). 또 다른 것은 당연히 i의 가치가 점프를 가로 질러 저장되는 것이 보장되지 않는다는 것입니다. i의 값은 지정되지 않습니다. 그래서 휘발성이 필요합니다. 그의 프로그램은 정의되지 않은 행동과 알려지지 않은 값에 의존합니다. 그러나 하루가 끝날 때,이 프로그램은 Standard의 PDF가 아닌 구현으로 실행됩니다. 따라서 그 사람이 자신이하는 일을 잘 안다면 그는 괜찮습니다. –

3

나에게 맞는 모양입니다. "일반"i ++는 for() 루프의 끝에서 발생합니다. longjmp (e, 1)를 호출하면 건너 뜁니다.

+0

지금 :(DOH 때까지이를 이해하지 못했다. –