2016-04-05 10 views
5

c'è una nota nella Swift Docs che indica quanto segue:Eccezioni Swift vs Obj-C. Cos'è lo stack unwinding? Perché Swift non lo fa?

manipolazione in Swift errore analogo gestione delle eccezioni in altre lingue, con l'uso del try, catch e gettare le parole chiave. Diversamente dalla gestione delle eccezioni in molte lingue, inclusa la gestione degli errori Objective-C in Swift, non è necessario srotolare lo stack delle chiamate, un processo che può essere costoso dal punto di vista computazionale. In quanto tale, le caratteristiche di prestazione di una dichiarazione di lancio sono paragonabili a quelle di una dichiarazione di ritorno.

Che cosa significa sganciare lo stack di chiamate in Swift e Obj-c? Related question here ma è specifico per C++. So qual è lo stack di chiamate, ma vorrei una spiegazione più dettagliata dello srotolamento.

Se Swift non svolge lo stack di chiamate, cosa fa invece?

Perché questo può essere oneroso dal punto di vista computazionale?

Riassunto: mi piacerebbe avere una migliore comprensione di come funzionano le eccezioni e il flusso di esecuzione in Swift.

risposta

2

Se si disattiva lo stack, significa che quando viene generata un'eccezione, il metodo viene immediatamente interrotto, il chiamante del metodo viene immediatamente interrotto e così via fino a quando viene trovato un gestore di eccezioni (try-catch-finally) o fino a raggiungere la parte superiore del stack, quando l'eccezione di solito termina con l'interruzione del thread corrente.

Che funziona abbastanza bene in lingue con un garbage collector ma in generale può portare a perdite di memoria in lingue con gestione manuale della memoria. Inoltre, poiché i metodi vengono interrotti in luoghi imprevisti, un'eccezione spesso porta a stati di programma indefiniti/non recuperabili.

Ecco perché l'eccezione in tutte le lingue deve essere utilizzata con parsimonia e solo per gestire situazioni eccezionali, non per gestire il normale flusso del programma.

Le eccezioni Obj-C non erano molto buone, con tutti i problemi sopra menzionati (vedere NSException, @[email protected]@finally), ecco perché nessuno li sta utilizzando. Invece, Obj-C è venuto con parametri di errore (si passa un riferimento a una variabile NSError e se il metodo fallisce, l'errore viene assegnato in quella variabile). Vedi Error Handling in Objective-C

Swift è appena arrivato con un'altra sintassi per NSError. Non è una vera gestione delle eccezioni (gli errori non interrompono l'esecuzione del programma). Vedi Error Handling in Swift

Tecnicamente, ogni funzione/metodo che può generare un errore in Swift ha solo un ulteriore parametro nascosto che viene utilizzato per passare l'errore al contesto del chiamante.

Se si desiderano ulteriori informazioni, confrontare il codice in Swift 1.xe 2.x (1.x non ha ancora una grammatica speciale per la gestione degli errori).

+2

Cosa non ho mai ricevuto: Ritorno da una funzione * lead * per impilare lo srotolamento. Certamente, passo dopo passo (alias call-by-call). Ma non riesco a capire, perché questo è meno costoso. –

+0

@ AminNegm-Awad Misurare davvero le prestazioni non è facile, ogni linguaggio e ogni compilatore usano un modello leggermente diverso. Ad esempio, puoi vedere http://stackoverflow.com/questions/13835817/are-exceptions-in-c-really-slow. Notare che l'impatto sulle prestazioni è importante quando si verifica effettivamente l'eccezione. Un altro motivo per non utilizzare mai eccezioni per il normale flusso del programma.Inoltre, tieni presente che un linguaggio di programmazione che non utilizza eccezioni può essere ottimizzato molto meglio dal compilatore, portando a prestazioni ancora migliori. – Sulthan

+2

@Sulthan La tua risposta ha aiutato grazie, ma hai detto che Swift ha un param nascosto che può passare indietro. Non vedo come questo sia diverso dallo srotolamento dello stack? Se chiamo un func one() che chiama func due() e due lancia un'eccezione che nè uno nè due maniglie, devo gestirlo nel mio codice chiamante. Ma qualsiasi affermazione dopo la chiamata a provare due() in uno non viene eseguita. Non è quello di ricomporre lo stack al chiamante? Quindi l'esecuzione continua dalla successiva dichiarazione del chiamante nel blocco catch. – Brynjar