2012-02-12 19 views
10

C'è questo codice:gestore delle eccezioni

char text[] = "zim"; 
int x = 777; 

Se guardo sulla pila in cui x e il testo sono messi lì di uscita è:

09 03 00 00 7a 69 6d 00 

Dove:

  • 09 03 00 00 = 0x309 = 777 < - int x = 777
  • 7a 69 6d 00 = testo carattere [] = "zim" (codice ASCII)

ora c'è codice con try..catch:

char text[] = "zim"; 
try{ 
    int x = 777; 
} 
catch(int){ 
} 

Stack:

09 03 00 00 **97 85 04 08** 7a 69 6d 00 

Ora tra testo e x è posto nuovo valore di 4 byte. Se aggiungo un altro fermo, quindi ci sarà qualcosa di simile:

09 03 00 00 **97 85 04 08** **xx xx xx xx** 7a 69 6d 00 

e così via. Penso che questo sia un valore collegato alla gestione delle eccezioni e che venga usato durante lo sbobinamento dello stack per trovare il catch appropriato quando viene lanciata un'eccezione nel blocco try. Comunque la domanda è, qual è esattamente questo valore a 4 byte (forse qualche indirizzo per la struttura del gestore di excception o qualche id)?

Uso g ++ 4.6 su macchina Linux a 32 bit.

+0

Vedere [C++ try/throw/catch => codice macchina] (http://stackoverflow.com/questions/1331220/c-try-throw-catch-machine-code), che rimanda a http: // www .codeproject.com/Articoli/2126/How-aC-compiler-implements-exception-handling –

+3

Perché vuoi sapere. Anche se ti avessimo dato una risposta sarebbe specifico per il compilatore e per quella specifica versione del compilatore. Quindi tecnicamente non è una domanda in C++. È una domanda su g ++ e su come funziona. Che a meno che tu non sia veramente interessato a scrivere estensioni per g ++ è una conoscenza completamente inutile. –

+4

@LokiAstari: g ++ e altri compilatori C++ per * nix utilizzano [Itanium ABI] (http://sourcery.mentor.com/public/cxx-abi/abi-eh.html) sulla maggior parte delle plaform (con alcune modifiche a seconda di la piattaforma), quindi non è * quella * piattaforma/compilatore specifico. Eppure, è interessante sapere come possono essere implementate le macchine per la gestione delle eccezioni. –

risposta

5

AFAICT, è un puntatore a una "tabella di svolgimento". Per il the Itanium ABI implementation suggestions, il processo "[utilizza] una tabella di unwind, [per] trovare informazioni su come gestire le eccezioni che si verificano su quel PC e, in particolare, ottenere l'indirizzo della routine della personalità per quell'intervallo di indirizzi."

L'idea alla base delle tabelle di unwind è che i dati necessari per lo srotolamento dello stack sono usati raramente. Pertanto, è più efficiente posizionare un puntatore sullo stack e memorizzare la prima parte dei dati in un'altra pagina. Nei casi migliori, quella pagina può rimanere su disco e non ha nemmeno bisogno di essere caricata nella RAM. In confronto, la gestione degli errori in stile C spesso finisce nella cache L1 perché è tutto in linea.

0

Inutile dire che tutto questo dipende dalla piattaforma e ecc

Questo può essere un indirizzo. Può indicare una sezione di codice (un indirizzo di gestore) o una sezione di dati (puntatore a una struttura generata in fase di generazione con informazioni di frame) o lo stack dello stesso thread (puntatore a una tabella generata in fase di esecuzione di frame info). Oppure può anche essere una spazzatura, lasciata a causa di un requisito di allineamento, che EH potrebbe richiedere.

Per esempio su Win32/x86 non c'è un tale spazio. Per ogni funzione che utilizza la gestione delle eccezioni (ha try/catch o __try/__except/__finally o oggetti con dorsori) - il compilatore genera una struttura EXCEPTION_RECORD allocata nello stack (dal codice funzione prolog). Quindi, ogni volta che qualcosa cambia all'interno della funzione (oggetto creato/distrutto, blocco try/catch inserito/chiuso) - il compilatore aggiunge un'istruzione che modifica questa struttura (più correttamente - modifica la sua estensione). Ma niente di più è assegnato in pila.