Pour une raison quelconque, quand je reviens du gestionnaire de signal pour SIGFPE, la variable i est un de moins que ce que j'attends, pour obtenir les bons résultats de mon programme (parcourir tous les les paires dans le tableau de paires) Je dois vérifier la valeur de retour de sigsetjmp et incrémenter i si je reviens d'un signal "catch". Pourquoi est-ce? Pourquoi l'incrémentation qui se produit lors de l'itération de l'exception à virgule flottante est-elle perdue?problème obscur avec sigsetjmp sur linux avec C
#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);
}
J'avais essayé de déclarer i volatile en vain, je pense la réponse de café est bon aussi. long/sigset/JMP était la seule chose que je pouvais constater que me laisserait sauter hors de la fonction de rappel et revenir à la boucle, sinon l'exception continue à émettre le signal encore et encore (c'est la division par zéro, donc je ne suis pas vraiment surpris), et pour sortir de cette boucle, je J'ai besoin de sauter du gestionnaire de signal dans un autre bloc de code.Je suppose que je peux utiliser un mutex autour de la stdio dans float_execption() –
Appeler * any * fonction de bibliothèque sauf signal() à partir d'un gestionnaire de signal est dangereux. J'ai été mordu par cela personnellement, nous avons appelé printf() depuis un gestionnaire de signal, mais au lieu d'écrire le message sur la console, il a écrasé la partie o f un fichier Access .mdb que nous étions en train de mettre à jour, arrosant la base de données de manière irréparable. Franchement, C ne fournit pas de très bons outils pour gérer des exceptions comme celle-ci; vous feriez bien mieux de vérifier vos arguments avant de tenter l'opération. –
@Ringding, wellDdivision par zéro est un comportement indéfini, donc Tom n'a aucune garantie (donnée par la norme C. La norme POSIX peut donner des garanties, je ne sais pas) qu'un signal arrive. Une autre chose est que, bien sûr, la valeur de i n'est pas garantie d'être stockée à travers le saut du tout. La valeur de i est non spécifiée. C'est pourquoi volatile est nécessaire. Son programme repose à la fois sur un comportement indéfini et sur des valeurs non spécifiées. Mais à la fin de la journée, le programme se déroule dans une mise en œuvre, pas sur le PDF standard, donc si le gars sait ce qu'il fait, il va bien. –