неясная проблема с sigsetjmp на Linux с C - PullRequest
0 голосов
/ 21 июля 2009

По какой-то причине, когда я возвращаюсь из обработчика сигнала для SIGFPE, переменная i на единицу меньше, чем я ожидаю, чтобы получить правильные результаты из моей программы (перебрать все пары в массиве пар) I должен проверить возвращаемое значение sigsetjmp и приращение i, если я возвращаюсь из сигнала «catch». Почему это? Почему приращение, которое происходит во время итерации исключения с плавающей запятой, теряется?

#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 ]

3 голосов
/ 21 июля 2009

Это выглядит правильно для меня. «Нормальный» i ++ происходит в конце цикла for () - и если вы вызываете longjmp (e, 1), вы пропускаете это.

0 голосов
/ 21 июля 2009

Ответ кафе кажется правильным.

Изначально я ожидал, что меня нужно объявить волатильным. По крайней мере, так утверждает автор NSBlog .

Еще одна вещь, на которую следует обратить внимание: это может быть опасно для вызова printf и fflush внутри обработчика сигнала. Учитывая тот факт, что SIGFPE является синхронным сигналом, об этом не может быть и речи, но вы должны знать, что делаете.

И, наконец, из справочной страницы Linux: «longjmp () и siglongjmp () делают программы трудными для понимания и сопровождения. Если возможно, следует использовать альтернативу».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...