J'ai quelques questions relatives à l'utilisation SETJMP / LONDJMP - P>
Quelle est l'utilisation de SETJMP (JMP ___ buf Stackvariables) renvoyant 0. Il s'agit d'une valeur par défaut, que nous ne pouvons pas influencer. p> li>
est la seule signification de SetJMP (StackVariables) consiste à appuyer sur la pile dans StackVariables. Et fondamentalement 0 nous dit si la pile a été poussée sur Stack_Variables avec succès. P> Li>
Leur est une occasion lorsque la valeur est non nulle (tout non-zéro) lorsque vous revenez d'un longJMP. Qu'est-ce qui revient d'un LOMGJMP, quand revenez-vous de LONGJMP lorsque votre exception est manipulée. Ceci est la configuration est vraiment déroutant. p> li>
Peut-on peut-être le rappeler pour essayer / lancer et attraper. Et serait vraiment génial, si de bons exemples de SETJMP / LONDJMP pourraient être fournis. P> LI>
est longJMP comme un lancer, et il est appelé juste après l'endroit où une exception peut être élevée. p> li> ol>
Merci. P>
4 Réponses :
SETJMP est utilisé pour placer un marqueur em> à l'endroit où l'appel de Longjump devrait retourner, il retourne 0 s'il est appelé directement, il renvoie 1 si elle est appelée parce qu'un longJMP est invoqué. Vous devez penser à SetJMP comme quelque chose qui peut être normalement appelé et ne fait rien (retourner 0) en fonctionnement normal tout en restituant 1 et il est invité indirectement (et retourne de là) lorsqu'un saut long est appelé. Je sais ce que tu veux dire de déroutant parce que c'est en fait déroutant. P> C'est l'exemple donné par Wikipedia: P> #include <stdio.h>
#include <setjmp.h>
static jmp_buf buf;
void second(void)
{
printf("second\n"); // prints
longjmp(buf,1); // jumps back to where setjmp was called - making setjmp now return 1
}
void first(void)
{
second();
printf("first\n"); // does not print
}
int main()
{
if ( ! setjmp(buf) )
{
first(); // when executed, setjmp returns 0
}
else
{ // when longjmp jumps back, setjmp returns 1
printf("main"); // prints
}
return 0;
}
Le problème que vous signalez est assez difficile à gérer car vous devez savoir tout ce qui a été attribué avant la longueur longue et comment le distribuer. En outre, IIRC, toute variables locales non volatiles dans la fonction qui émet que la SETJMP peut être corrompue.
La première partie est presque simple: lorsque vous faites une longueur longue, vous vous retrouvez exactement après le SETJMP. Si la valeur de retour est 0, cela signifie que vous venez de faire le SETJMP; Si ce n'est pas nul, vous savez que vous êtes arrivé à partir d'un longjmp d'ailleurs. Cette information est souvent utile pour contrôler ce que votre code fait après cela. P>
SETJMP / LONDJMP sont les anciens ancêtres de lancer / attrape. SETJMP / LONDJMP est défini en C, tandis que Jet / Catch est le mécanisme plus "moderne" pour faire la récupération des erreurs dans des langages plus orientés objet tels que C ++. P>
appeler LONDJMP dit: "Je pense qu'il y a quelque chose de mal ici, aidez-moi, me faire sortir d'ici - je suis trop confus de nettoyer après moi-même et de revenir à travers un tas d'appels de fonctions et si elle est juste de retour à où le monde était d'accord à nouveau, juste après la dernière SETJMP. " P>
Jeton dit à peu près la même chose, à l'exception de la syntaxe plus clairement et propre à la syntaxe. De plus, tandis que LongJMP peut vous emmener à pratiquement n'importe quel endroit du programme (où que vous fassiez le SETJMP), le lancer se termine directement vers le haut dans la hiérarchie des appels de l'endroit où se trouve le lancer. P>
La spécification C99 donne:
Si le retour provient d'une invocation directe, la macro SETJMP renvoie la valeur zéro. Si la Le retour est d'un appel à la fonction LONGJMP, la macro SetJMP renvoie un non nul. valeur. p> blockquote>
donc la réponse à 1 est qu'un zéro indique que vous avez appelé
setjmp code> la première fois et non-zéro indique qu'il renvoie à partir d'un
longjmp code> . P>
Il pousse l'état actuel du programme. Après une longjmp, l'état est restauré, le contrôle revient au point qu'il a été appelé, et la valeur de retour est non nulle. P> li>
Il n'y a pas d'exception dans C. Il est similaire à
Fork Code> Renvoyer des valeurs différentes selon que vous êtes dans le processus d'origine, ou un deuxième processus qui a hérité de l'environnement, Si vous connaissez cela. p> li>
Essayez code> /
Catch code> en C ++ appellera des destructeurs sur tous les objets automatiques entre le lancer et la capture.
setJMP code> /
longjmp code> ne appelle pas les destructeurs, car ils n'existent pas dans C. Vous êtes de sorte que vous êtes seul pour appeler
gratuit code> sur Tout ce que vous avez
MALLOC code> ED dans la période moyenne. P> LI> ol>
avec cette réserve, ceci: p>
xxx pré> est à peu près équivalent à p>
xxx pré> dans le c Cas, vous devez faire une gestion de la mémoire explicite (bien que normalement vous libéreriez-la dans la fonction qui a déjà appelé LongJMP car elle simplifie la vie) P> P>
Est-ce que LongJMP est un lancer, et il est appelé juste après l'endroit où une exception peut être élevée. Et aussi, pourquoi utilisez-vous le numéro 42, vous pouvez faire le même travail 1 ou 42 tout non-zéro in int.
Le point clé est que la fonction SETJMP () peut revenir une fois, ou elle peut renvoyer plusieurs fois. Il reviendra une fois à partir de l'invocation directe (qui reviendra 0); Tous les retours suivants sont le résultat d'une longueur longue () et retournera une valeur non nulle.
Vous ne pouvez pas générer de manière générale du résultat de SETJMP () dans une variable. La norme C indique: "L'invocation de la macro SETJMP ne doit apparaître que dans l'un des contextes suivants: toute l'expression de contrôle d'une instruction de sélection ou d'une itération; un opérande d'un opérateur relationnel ou d'égalité avec l'autre opérande une expression constante entière, avec l'expression résultante étant toute l'expression contrôlée d'une déclaration de sélection ou d'itération; l'opérande d'un "opérateur avec l'expression résultante étant [...]; ou toute l'expression d'une déclaration d'expression [...]".
@Jonathan Leffler Vous avez raison, mais il est difficile de démontrer la valeur de retour dans le code de démonstration si vous ne le faites pas.
Juste pour ajouter à la réponse (et remarque) de Pete Kirkham: puisque C Standard ne permet pas de stocker la valeur de retour de SETJMP, l'exemple de Pete pourrait peut-être être modifié à la place. Il démontre toujours comment distinct entre différentes valeurs de retour, mais ne violent pas la norme.
#include <stdio.h> #include <setjmp.h> #include <string.h> #include <stdlib.h> void foo(char** data) ; void handle(char* data) ; jmp_buf env; int main(void) { char* data = 0; switch(setjmp(env)) { case 0: { printf("setjmp returned 0\n"); foo(&data); break; } case 42: { printf("setjmp returned 42\n"); handle ( data ); break; } default: { printf("setjmp returned something else?\n"); } } return 0; } void foo(char** data) { *data = malloc(32); printf("in foo\n"); strcpy(*data, "Hello World"); printf("data = %s\n", *data); longjmp(env, 42); } void handle(char* data) { printf("in handler\n"); if(data) { free(data); printf("data freed\n"); } }