使用C在Linux上使用sigsetjmp时出现的问题

时间:2009-07-21 13:28:39

标签: c linux

由于某种原因,当我从SIGFPE的信号处理程序返回时,变量i比我预期的要少一个,从我的程序中获得正确的结果(遍历对数组中的所有对)I如果我从信号“catch”返回,必须检查sigsetjmp的返回值并增加i。为什么是这样?为什么在浮点异常的迭代过程中发生的递增会丢失?

#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);
}

2 个答案:

答案 0 :(得分:3)

这对我来说是对的。 “正常”i ++发生在for()循环的末尾 - 如果你调用longjmp(e,1),你就跳过它。

答案 1 :(得分:0)

caf的答案似乎是正确的。

我最初的期望是,我需要声明为volatile。至少那是NSBlog claims的作者。

另外需要注意的一点是:在信号处理程序中调用printf和fflush可能是dangerous。鉴于SIGFPE是同步信号这一事实,它并非完全不可能,但您应该知道自己在做什么。

最后,从Linux手册页:“longjmp()和siglongjmp()使程序难以理解和维护。如果可能的话,应该使用替代方案。”