Benvenuti su "Just a Bit of.. Entropy!".
Questo blog tratta di Free Software e programmazione.
L'autore è un di membro di Guru@Work
e studente del corso di laurea specialistica in
Tecnologie Informatiche all'università di Pisa.
GoTo: No_Grazie;

Dopo aver letto questa vignetta mi è tornato in mente un quesito teorico che faceva bella mostra di se’ nel Mid Term di Programmazione Avanzata consegnato qualche mesetto fa…
Il quesito era il seguente:
“Spiegare il meccanismo delle eccezioni e le tecniche per implementarlo nel run-time di un linguaggio. Spiegare quali costi incorrono per il trattamento delle eccezioni sia le procedure che le sollevano che quelle che le gestiscono. Ci sono dei costi anche per le procedure che non trattano eccezioni?
Si potrebbe utilizzare un costrutto di goto non locale, presente ad esempio in Pascal, per ottenere lo stesso effetto di una eccezione?
Quali delle considerazioni che sconsigliano l’uso dei goto valgono anche per le eccezioni?”
Ricercando un po’ ho trovato anche la mia risposta, la riporto qui di seguito (non perché sia particolarmente bella\entusiasmante\fondamentale-per-la-vita-di-chi-legge, quanto perché l’argomento in se per se è abbastanza interessante..)
Il runtime di un linguaggio, per implementare tale meccanismo, può rendere disponibili al programmatore dei costrutti che consentono l’invocazione di codice da questi definito per l’occasione specifica.
In Java tale è lo scopo del costrutto try{…}catch(Exception e){…} che permette, se l’eccezione sollevata dal codice del bloco try è del tipo (o di un sottotipo) di quella presente nella guardia, di gestirla eseguendo il codice del blocco successivo.
La struttura dati necessaria all’implementazione di tale mecanismo nel runtime di un linguaggio è una tabella accedibile tramite il codice di eccezione e contenente, per questo, l’apposita handle alla procedura che ne effettua la gestione.
Nel caso di Java questa procedura risulta quella riscritta dal programmatore stesso, se presente, alternativamente tramite il meccanismo dell’ereditarietà si va a risalire nella gerarchia delle eccezioni sino a che non se ne trova una gestita.
Si considera che il metodo main di qualsiasi programma sia in grado di gestire una generica Exception e per tale motivo se le chiamate, propagandosi nella gerarchia delle eccezioni, non trovano alcuna gestione sino alla classe contenente il metodo main vengono segnalate a fase di esecuzione come errori, causando l’intrruzione dell’applicativo.
I costi per la gestione delle eccezioni sono esprimibili valutando i livelli di indirezione che si spendono per calcolare l’indirizzo della procedura da invocare, la gestione della struttura dati presente e i costi necessari alla procedura di gestione reperita per ripristinare, al termine della sua esecuzione, dello stato precedente dell’applicazione.
Inoltre un applicativo che non gestisca le proprie eccezioni paga in ogni caso il costo della tabella degli handler poiché in caso di errore (o eccezione) a runtime questo deve essere propagato sino al metodo main dove viene ricercato in ultima istanza un gestore.
In Pascal è possibile definire delle Label (identificanti un indirizzo nell’area di codice del programma) a cui saltare con un costrutto di tipo goto.
Tali costrutti consentono anche salti non locali (un esempio sono le funzioni setjmp() e longjmp() dello standard C) che consentono di salvare uno stato del programma conosciuto per buono e di ripristinarlo in caso di errore.
Questa strada consente di gestire senza indirezioni le eventuali eccezioni (o errori) che si presentino a runtime, a patto di conoscere staticamente la locazione in cui queste sono definite, e di ridefinire a tempo di stesura del codice tutto il meccanismo di gestione.
I costi sono quindi meno onerosi relativamente a quelli pagabili per l’uso di un gestore di eccezioni sul tipo di quello offerto da Java (per quanto riguarda la gestione delle strutture dati, non presenti, e per il reperimento dell’indirizzo della routine di gestione).
Per quando riguarda invece la sicurezza grazie alla regola dello “handle or declare” (gestisci o dichiara), che obbilga il programmatore a prevedere esplicite contromisure per ogni situazione anomala (prevedibile) il meccanismo delle eccezioni risulta certamente più affidabile. Inoltre il costo di gestione della struttura dati per la gestione degli Handle è ripagata dalla non necessità di definire al momento di stesura del codice gli indirizzi alle routine di trattamento di cui non necessariamente (ad esempio nel caso di ereditarietà) si conosce l’indirizzo.
I goto, come le eccezioni, interrompono il flusso normale di esecuzione di un programma. A basso livello anche il meccanismo delle eccezioni è gestito utilizzando il costrutto goto non locale (seppur in modo da limitare i possibili problemi di quest’ultimo).
Come a seguito dell’uso di goto, dopo che viene sollevata un eccezione non sono liberate le struttre dati precedentemente utilizzate dal programma (a meno che questo non sia fatto, se possibile, dal programmatore durante la fase di gestione).
L’uso di goto a differenza della gestione delle eccezioni rende il codice meno leggibile ed è per questo motivo sconsigliato un suo uso improprio quando sostituibile con altri costrutti: questo vale anche per i blocchi try-catch che, talvolta, vengono usati all’interno di cicli per interrompere l’esecuzione in caso di risultati non voluti e riprenderla dall’iterazione successiva.
L’abuso di tali costrutti porta a una gestione del codice più articolata per il programmatore, una scarsa leggibilità e, prevedendo la modifica del flusso di esecuzione, una gestione dello stack non ottimale in alcuni casi.”
[N.B: Uno dei primi linguaggi con cui mi son avvicinato, anni fa, alla programmazione è stato proprio il Pascal.. e si se non si è capito odio i goto
]
Blog realizzato da Giulio Rossetti.
Immagine presente nell'header realizzata da bunocb e disponibile sul sito crystalxp





































