Quale codice si trova dietro l'eccezione C ++?

2

In C e C ++ puoi restituire una singola variabile all'interno di una funzione. Ora, nel caso in cui la variabile restituisca dati e non un codice di errore, è possibile utilizzare le eccezioni. Ma come è possibile? Se i dati che vengono restituiti sono i dati che comunichi alla funzione di restituire, allora non c'è praticamente alcun modo per la funzione di chiamarla per sapere che è successo (perché il ritorno è usato per i dati, e non un codice di errore). Inoltre, la possibilità per un'eccezione di interrompere letteralmente la funzione nel mezzo del codice per restituire l'errore. Come fanno i compilatori C ++ a raggiungere questo obiettivo?

    
posta Stephen Boswell 05.10.2013 - 12:45
fonte

2 risposte

4

Quando una funzione genera un'eccezione, non restituisce un valore del tipo specificato dalla specifica della funzione e non ritorna al punto in cui è stata richiamata la funzione. Invece "restituisce" un oggetto eccezione e "restituisce" quell'oggetto a qualsiasi blocco catch che cattura quel particolare tipo di eccezione.

Che metto "ritorni" tra virgolette è intenzionale. È meglio non pensare a throw come restituire un valore. Getta invece un valore al blocco catch che gestisce l'eccezione. Il meccanismo per la gestione della chiamata e del ritorno delle normali funzioni è quasi sempre implementato sotto forma di stack di chiamate.

La gestione delle eccezioni funziona con un meccanismo diverso rispetto allo stack di chiamate, ma tale meccanismo di gestione delle eccezioni deve farlo in modo coerente con lo stack di chiamate. Il blocco catch che cattura un'eccezione generata potrebbe essere più chiamate al di sopra della funzione che ha chiamato la funzione che ha generato l'eccezione. Tutte le cose che intervengono, le variabili temporanee passate come argomenti e le variabili locali dichiarate in quelle funzioni intervenienti, devono essere ripulite lungo il percorso. Questo è chiamato "unwinding the stack".

    
risposta data 05.10.2013 - 14:18
fonte
0

Esistono diversi malintesi alla base della tua domanda.

Prima di tutto, la distinzione che si ottiene tra la restituzione dei dati o un codice di errore è una distinzione artificiale. I linguaggi C e C ++ non hanno questa distinzione. Per loro si restituiscono sempre i dati. Solo noi programmatori associamo il significato di un codice di errore ad alcuni di quei dati.

In secondo luogo, quando si esce da una funzione, non è necessario tornare indietro nel punto in cui è stata chiamata la funzione. Puoi finire in una posizione completamente diversa del codice.

Ora, le eccezioni possono essere implementate in vari modi. Traccerò uno di questi modi. Non è il più efficiente, ma è uno dei più facili da capire.

Per prima cosa spiegherò come funziona una chiamata di funzione normale. Quando si chiama una funzione nel codice C o C ++, il compilatore genera istruzioni per eseguire diversi passaggi. Prima i (valori di) gli argomenti della funzione vengono inseriti nello stack. Quindi viene inviato l'indirizzo dove continuare l'elaborazione dopo il ritorno della funzione (con un ritorno normale). Infine, un salto viene eseguito alla prima istruzione della funzione.

Per la gestione delle eccezioni, il compilatore genera alcune informazioni aggiuntive che vengono inserite nello stack insieme alle variabili locali. Questa informazione dice all'istruzione throw come pulire quelle variabili locali e dove si trovano i blocchi catch . Quando viene generata un'eccezione, l'istruzione throw cammina sopra lo stack per cercare un blocco catch appropriato, pulendo le variabili locali che trova lungo il percorso. Quando è stato trovato un blocco catch appropriato, viene eseguito un salto per continuare l'esecuzione in quel punto.

Come puoi vedere, il ritorno da una funzione e il lancio di un'eccezione utilizzano informazioni completamente diverse su dove continuare l'esecuzione dopo il ritorno / lancio. Per questo motivo, se una funzione non indica errori con un codice di errore, ma utilizza eccezioni, è possibile presumere che la funzione abbia avuto successo se ritorna dalla sua chiamata. Se la funzione era stata lanciata, il codice immediatamente successivo alla chiamata della funzione non sarebbe stato eseguito.

    
risposta data 06.10.2013 - 11:11
fonte

Leggi altre domande sui tag