setjmp
Section: C Library Functions (3)
Updated: 5 février 2023
Index
Return to Main Contents
NOM
setjmp, sigsetjmp, longjmp, siglongjmp - Effectuer un saut non local
BIBLIOTHÈQUE
Bibliothèque C standard (libc, -lc)
SYNOPSIS
#include <setjmp.h>
int setjmp(jmp_buf env);
int sigsetjmp(sigjmp_buf env, int sauvsigs);
[[noreturn]] void longjmp(jmp_buf env, int val);
[[noreturn]] void siglongjmp(sigjmp_buf env, int val);
Exigences de macros de test de fonctionnalités pour la glibc (consulter
feature_test_macros(7)) :
setjmp() : consultez la section NOTES.
sigsetjmp():
_POSIX_C_SOURCE
DESCRIPTION
Les fonctions décrites dans cette page sont utilisées pour effectuer des
« sauts non locaux » : transfert de l'exécution d'une fonction à un
emplacement prédéterminé d'une autre fonction. La fonction setjmp()
établit de façon dynamique l'emplacement vers lequel le contrôle sera
transféré ultérieurement et longjmp() se charge de transférer
l'exécution.
La fonction setjmp() sauvegarde diverses informations concernant
l'environnement de l'appelant (typiquement le pointeur de pile, le pointeur
d'instruction, potentiellement les valeurs d'autres registres ainsi que le
masque de signaux) dans le tampon env pour son utilisation ultérieure par
longjmp(). Dans ce cas, setjmp() renvoie 0.
La fonction longjmp() utilise les informations stockées dans env pour
transférer le contrôle à l'endroit où setjmp() fut appelé et restaurer
(« rewind ») la pile à son état lors de l'appel à setjmp(). De plus, et
en fonction de l'implémentation (voir NOTES), les valeurs d'autres registres
et le masque de signaux du processus peuvent également être restaurées à
leur état lors de l'appel à setjmp().
Après un appel réussi à longjmp(), l'exécution continue comme si
setjmp() avait renvoyé une deuxième fois. Ce renvoi « factice » peut être
distingué d'un vrai appel à setjmp() car il renvoie la valeur contenue
dans val. Si le programmeur passe la valeur 0 à val par
inadvertance, le renvoi « factice » retourne 1 à la place.
sigsetjmp() et siglongjmp()
sigsetjmp() et siglongjmp() effectuent également des sauts non locaux
mais permettent une gestion prévisible du masque de signaux du processus.
Si, et seulement si, l'argument sauvsigs passé à sigsetjmp() est non
nul, le masque de signaux actuel du processus est sauvegardé dans env et
sera rétabli lorsque siglongjmp() sera invoquée avec ce contexte env.
VALEUR RENVOYÉE
setjmp() et sigsetjmp() renvoient 0 lorsqu'elles sont appelées
directement ; la valeur non nulle spécifiée dans val est renvoyée lors du
renvoi « factice » qui se produit après un appel à longjmp() ou
siglongjmp().
Les fonctions longjmp() et siglongjmp() ne renvoient pas.
ATTRIBUTS
Pour une explication des termes utilisés dans cette section, consulter
attributes(7).
Interface | Attribut | Valeur
|
setjmp(),
sigsetjmp()
| Sécurité des threads | MT-Safe
|
longjmp(),
siglongjmp()
| Sécurité des threads | MT-Safe
|
STANDARDS
setjmp(), longjmp() : POSIX.1-2001, POSIX.1-2008, C99.
sigsetjmp(), siglongjmp() : POSIX.1-2001, POSIX.1-2008.
NOTES
POSIX ne spécifie pas si setjmp() sauve le masque de signaux (pour être
ensuite restauré lors de longjmp()). Sous System V, ce n'est pas le
cas. Sous 4.3BSD, le masque sera sauvé et il y a une fonction _setjmp qui
ne fait pas la copie. Le comportement sous Linux dépend de la version de la
glibc ainsi que de la configuration des macros de test de
fonctionnalités. Avant la glib 2.19, setjmp() suit le comportement de
System V par défaut, mais le comportement BSD est fourni si la macro de test
de fonctionnalités _BSD_SOURCE est définie et qu’aucune des macros
_POSIX_SOURCE, _POSIX_C_SOURCE, _XOPEN_SOURCE, _GNU_SOURCE ou
_SVID_SOURCE n'est définie. Depuis la glibc 2.19, <setjmp.h>
n’expose que la version System V de setjmp(). Les programmes ayant besoin
de la sémantique BSD devraient remplacer les appels de setjmp() par des
appels de sigsetjmp() avec un argument sauvsigs non nul.
setjmp() et longjmp() peuvent être utiles pour gérer des erreurs dans
des appels profondément imbriqués ou pour permettre à un gestionnaire de
signal de passer le contrôle à un point précis du programme, plutôt que de
renvoyer là où le gestionnaire a interrompu le programme principal. Dans ce
dernier cas, si vous désirez sauvegarder et restaurer les masques de signaux
de manière portable, utilisez sigsetjmp() et siglongjmp(). Consultez
également la sous-section sur la lisibilité des programmes ci-dessous.
Le compilateur peut optimiser certaines variables dans des registres et
longjmp() peut restaurer les valeurs d'autres registres en plus des
pointeurs de pile et d'instruction. Par conséquent, les valeurs de variables
automatiques ne sont pas spécifiées après un appel à longjmp() si elles
satisfont à tous les critères suivants :
- •
-
elles sont locales à la fonction qui a effectué l'appel correspondant à
setjmp() ;
- •
-
leur valeur est changée entre les appels à setjmp() et longjmp() ;
- •
-
elles ne sont pas déclarées comme volatile.
Ces remarques s'appliquent aussi à siglongjmp().
Sauts non locaux et lisibilité des programmes
Bien que la déclaration C traditionnelle « goto » puisse être exploitée,
elle a pour bénéfice que les repères lexicaux (la déclaration de saut ainsi
que l'étiquette cible) permettent au programmeur de percevoir de façon
claire le flux de contrôle. Les sauts non locaux ne fournissent pas de tels
repères : plusieurs appels à setjmp() peuvent utiliser la même variable
jmp_buf de telle sorte que son contenu change au cours du déroulement de
l'application. Par conséquent, le programmeur peut être astreint à une
lecture détaillée du code afin de déterminer la cible dynamique d'un appel
longjmp() particulier (pour rendre la tâche du programmeur plus simple,
chaque appel à setjmp() devrait utiliser une variable jmp_buf unique).
De façon encore plus compliquée, les appels à setjmp() et longjmp()
peuvent même provenir de modules de code source différents.
En résumé, les sauts non locaux peuvent rendre les programmes plus
difficiles à comprendre et à maintenir, et une alternative devrait être
utilisée lorsque c'est possible.
Mises en garde
Si la fonction qui a appelé setjmp() renvoie avant que longjmp() ne
soit appelée, le comportement n'est pas défini. Une sorte de chaos plus ou
moins subtil en résulterait de façon certaine.
Si, dans un programme à plusieurs fils d'exécution, un appel à longjmp()
utilise un tampon env initialisé préalablement par setjmp() dans un
fil d'exécution différent, le comportement n'est pas défini.
Le Technical Corrigendum 2 de POSIX.1-2008 ajoute longjmp() et
siglongjmp() à la liste des fonctions sûres vis-à-vis des signaux
asynchrones. Cependant, la norme recommande de ne pas utiliser ces fonctions
dans un gestionnaire de signal et indique ensuite que si ces fonctions sont
appelées depuis un gestionnaire de signal qui a interrompu un appel à une
fonction non sûre vis-à-vis des signaux asynchrones (ou similaire tels que
les étapes équivalentes à exit(3) se produisant après un renvoi de
l'appel initial main()), le comportement n'est pas défini si le programme
fait par la suite un appel à une fonction non sûre vis-à-vis des signaux
asynchrones. La seule façon d'éviter ce comportement non défini est de
s'assurer de la chose suivante :
- •
-
Après un saut non local depuis un gestionnaire de signal, le programme
n'appelle pas de fonction non sûre vis-à-vis des signaux asynchrones et ne
renvoie pas depuis l'appel initial à main().
- •
-
Chaque signal dont le gestionnaire effectue un saut non local doit être
bloqué lors de chaque appel à une fonction non sûre vis-à-vis des signaux
asynchrones et aucune fonction non sûre vis-à-vis des signaux asynchrones
n'est appelée après un renvoi depuis l'appel initial à main().
VOIR AUSSI
signal(7), signal-safety(7)
TRADUCTION
La traduction française de cette page de manuel a été créée par
Christophe Blaess <https://www.blaess.fr/christophe/>,
Stéphan Rafin <stephan.rafin@laposte.net>,
Thierry Vignaud <tvignaud@mandriva.com>,
François Micaux,
Alain Portal <aportal@univ-montp2.fr>,
Jean-Philippe Guérard <fevrier@tigreraye.org>,
Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>,
Julien Cristau <jcristau@debian.org>,
Thomas Huriaux <thomas.huriaux@gmail.com>,
Nicolas François <nicolas.francois@centraliens.net>,
Florentin Duneau <fduneau@gmail.com>,
Simon Paillard <simon.paillard@resel.enst-bretagne.fr>,
Denis Barbier <barbier@debian.org>,
David Prévot <david@tilapin.org>
et
Grégoire Scano <gregoire.scano@malloc.fr>
Cette traduction est une documentation libre ; veuillez vous reporter à la
GNU General Public License version 3
concernant les conditions de copie et
de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page de manuel,
veuillez envoyer un message à
Index
- NOM
-
- BIBLIOTHÈQUE
-
- SYNOPSIS
-
- DESCRIPTION
-
- sigsetjmp() et siglongjmp()
-
- VALEUR RENVOYÉE
-
- ATTRIBUTS
-
- STANDARDS
-
- NOTES
-
- Sauts non locaux et lisibilité des programmes
-
- Mises en garde
-
- VOIR AUSSI
-
- TRADUCTION
-
This document was created by
man2html,
using the manual pages.
Time: 13:53:13 GMT, May 22, 2024