2009-07-03 7 views
8

Sto cercando di implementare la gestione delle eccezioni per un sistema operativo integrato e sono bloccato su come rilevare il tipo di "eccezione" generata (per selezionare il gestore appropriato).Qual è la più semplice implementazione RTTI per C++?

di salvare e ripristinare le parti contesto della gestione delle eccezioni sono già fatto, ma non posso avere le maniglie specifici quanto non riesco a rilevare il tipo di 'eccezioni' buttato. L'implementazione RTTI standard di C++ è troppo dipendente da altre librerie e per questo motivo attualmente la sto considerando non disponibile.

Considerando che il mio obiettivo è un sistema embedded e per questo motivo non riesco a creare molto codice, qual è la più piccola implementazione di "Informazioni sul tipo di runtime" che posso ottenere (o creare)?

- Modifica -

non sto lavorando sul compilatore, si tratta di un ia32-g ++.

+1

Stai scrivendo/modificando il compilatore o il runtime della lingua, o dove esattamente vuoi inserire questo? Un po 'più di contesto sarebbe bello. – jalf

+0

Se la memoria è limitata, non abilitare RTTI o tentare di utilizzare eccezioni.Meglio pensare a un approccio alternativo. –

+0

Se è stata lanciata un'eccezione, in qualche modo il tiro ha codificato le informazioni sul tipo di eccezione, quindi non vedo perché è necessario un metodo "alternativo". Come disse Jalf, dacci maggiori informazioni su ciò che stai effettivamente cercando di fare. –

risposta

11

Come si lavora in un ambiente integrato, si favorirebbe probabilmente soluzioni estremamente minimale e si può usufruire di non standard o non-portatili fatti circa il compilatore.

Se una classe è polimorfica (ha almeno una propria funzione virtuale) in C++, probabilmente ha un puntatore a un vtable incorporato da qualche parte in esso. Può darsi che il puntatore vtable appaia all'inizio del layout dell'oggetto in memoria.

Questo è vero per molti compilatori, quelli che utilizzano il C++ ABI - a related SO question here.

Se è così, si potrebbe essere in grado di arrivare alla vtable in questo modo:

void *get_vtable(void *obj) 
{ 
    return *(reinterpret_cast<void **>(obj)); 
} 

Quindi è possibile confrontare i VTables di due puntatori-a-oggetti per vedere se puntano allo stesso tipo di oggetto.

Quindi un "tipo di switch" (che è ciò che cattura fondamentalmente) avrebbe fatto qualcosa di simile:

P p; 
Q q; 
if (get_vtable(caught) == get_vtable(&p)) 
{ 
    // it's a P... 
} 
else if (get_vtable(caught) == get_vtable(&q)) 
{ 
    // it's a Q... 
} 

Si potrebbe nascondere quel modello in una macro CATCH.

Punto importante - se si deriva una classe da una base, ma la classe derivata non ridefinisce le funzioni virtuali o aggiungere nuovi funzioni virtuali, allora il compilatore, concettualmente, potrebbe riutilizzare vtable della classe base per la classe derivata. Ciò significa che, al fine di distinguere tra due tipi di eccezione, ognuno deve ignorare una funzione virtuale, per garantire che abbiano i propri vtables.

notare che questa è solo una piccola frazione di quello che comporta la gestione delle eccezioni. C'è anche la piccola questione di srotolare lo stack! Devi chiamare i distruttori di tutti gli oggetti in pila quando salti sul gestore. Non si tratta solo di fare setjmp/longjmp.

+0

Puoi mostrare un modo per ottenere il 'ptr' nel primo codice? E non ho capito il ruolo di 'obj'. – freitass

+0

Mi dispiace, quello era un errore di battitura. È solo un puntatore a un oggetto di tipo polimorfico. –

2

Il RTTI più semplice mi viene in mente è quello di derivare tutte le classi da una base comune che hanno una "GetType) (" funzione virtuale pura. O ottenerlo per restituire una stringa o creare un enum enorme con tutti i tipi in esso. È piuttosto semplice, veloce e con memoria insufficiente. Non particolarmente flessibile, tuttavia.

+0

Ovviamente, per l'esistenza di funzioni virtuali, probabilmente si utilizza una sorta di tabella dei puntatori a funzione virtuale. Che in qualche modo potrebbe essere fatto per essere utilizzato per rti ... – gimpf

+0

un po 'più coinvolto rispetto al metodo enum gigante però) – Goz

+0

Dovrebbe aggiungere anche un po' meno cross platform ... trovare quelle VTables può essere un duro lavoro. – Goz