• Non ci sono risultati.

Permettono ad una funzione annidata a livelli profondi di restituire direttamente il controllo ad un livello più esterno

N/A
N/A
Protected

Academic year: 2021

Condividi "Permettono ad una funzione annidata a livelli profondi di restituire direttamente il controllo ad un livello più esterno"

Copied!
3
0
0

Testo completo

(1)

Salti non locali

Ver. 2.4

© 2010 - Claudio Fornaro - Corso di programmazione in C

2

Scopo

Permettono ad una funzione annidata a livelli profondi di restituire direttamente il controllo ad un livello più esterno

Esempio:

a () chiama b () che chiama c () che chiama d () Un salto non locale permette ad esempio a d() di tornare immediatamente ad a() senza passare dalle funzioni intermedie c() e b()

Questo metodo viene utilizzato soprattutto per la gestione degli errori e dei segnali (ad es.

divisione per 0, interrupt, etc.)

Funzioni e strutture dati sono in <setjmp.h>

3

Funzionamento

Lo stato attuale del programma (alcuni registri della CPU, tra cui Program Counter, Stack Pointer e Frame Pointer) viene salvato in una variabile di tipo jmp_buf dalla

funzione setjmp

Il salto non locale avviene tramite la funzione longjmp che ripristina lo stato antecedente alla chiamata a setjmp utilizzando i dati memorizzati in jmp_buf: quindi l’esecuzione torna alla setjmp e prosegue dall’istruzione successiva ad essa

Non è un’istruzione strutturata

4

Preparazione al salto

int setjmp(jmp_buf env)

salva lo stato del programma nella variabile indicata (env). La chiamata a longjmp ritornerà a questo punto e l’esecuzione continuerà dall’istruzione successiva.

Restituisce valore 0 dopo la chiamata a setjmp, valore diverso da 0 se di ritorno dalla longjmp

Nota: la funzione che contiene la longjmp deve poter accedere a env, quindi env :

viene passato di funzione in funzione fino a quella che contiene la longjmp

oppure viene definito come variabile esterna

(2)

5

Esecuzione del salto

void longjmp(jmp_buf env, int val) ripristina lo stato salvato in env, l’esecuzione continua come se fosse appena stata eseguita la setjmp che però ora non restituisce 0, ma val (che non può essere pari a 0)

Poiché viene ripristinato lo stack alla

situazione precedente la chiamata a setjmp, lo stack stesso viene liberato da tutte le

allocazioni dovute alle chiamate di funzione successive alla chiamata setjmp

Non ha senso chiamare una longjmp per ripristinare la situazione memorizzata (da una setjmp) da una funzione ormai terminata

6

Schema della setjmp

if (setjmp(env) == 0)

/* esegue questo blocco se si tratta della chiamata diretta che salva lo stato

*/

else

/* esegue questo blocco se è di ritorno dalla longjmp

*/

7

Esempio

#include <stdio.h>

#include <setjmp.h>

jmp_buf buf;

void f2() { longjmp(buf,1); } void f1() { f2(buf); }

main() {

if (setjmp(buf)==0) {

printf("CHIAMATA SETJMP\n");

f1(buf);

} else

printf("CHIAMATA LONGJMP\n");

}

8

Gestione dell’errore

La setjmp permette di isolare (proteggere) blocchi di codice che possono generare

problemi e farli seguire da un blocco di codice per il trattamento del caso di errore

if (setjmp(buf)==0) {blocco A}

else

{gestione errore del blocco A}

if (setjmp(buf)==0) {blocco B}

else

{gestione errore del blocco B}

(3)

9

Restrizione sulla setjmp

Le variabili automatiche che sono state modificate dopo la chiamata a setjmp, al ritorno per effetto di una longjmp hanno contenuto indefinito

Per preservarne il contenuto si deve usare la clausola volatile davanti alle definizione (questo indica al compilatore di non fare alcuna ottimizzazione, ad es. di non collocarle nei registri):

volatile int x;

struct nodo * volatile sp;

Riferimenti

Documenti correlati

Si scrivano in particolare le equazioni degli asintoti e le ascisse dei punti di massimo, di minimo e di flesso.. La funzione ha un asintoto orizzontale per x

Pertanto, x = 0 `e un punto di salto per f e, quindi, mancando la continuit` a, la funzione non sar` a neppure derivabile nell’origine... Per l’enunciato e la dimostrazione del

Andrea, Cersosimo, Chiaromonte, Episcopia, Fardella, Francavilla in Sinni, Lagonegro, Lauria, Latronico, Maratea, Nemoli, Noepoli, Rivello, Roccanova, Rotonda,

L'indirizzo dell'Ufficio locale, cui è stato assegnato nel codice amministrativo n.1 il numero 14130, è: - Via Falmerayer n.9, C.A.P. Allegato

tenuto conto che dal 1° ottobre 2018 si renderà disponibile l’incarico di funzione dirigenziale di livello generale di Responsabile della Direzione centrale

tenuto conto che dal 1° maggio 2020 si renderà disponibile l’incarico di funzione dirigenziale di livello generale di Responsabile della Direzione centrale

conta_divisibili (int quadrati[], int valori[], int n_valori, int contatori[]) che scrive in ciascun elemento del vettore contatori (anch’esso di dimensione N) quanti elementi

che scrive in ciascun elemento del vettore contatori (anch’esso di dimensione N) quanti elementi del vettore valori sono divisibili per il numero primo presente nella