"Ron Natalie" <ro*@spamcop.ne twrote in message
news:45******** **************@ news.newshostin g.com...
>
It is NOT THE CASE that this can be determined at COMPILE time.
And yet, it is the case. Let's reorder a bit and, hmm, compile...
int main() {
__main:
try {
Thrower();
} catch (Super*) { ...
..DATA SEGMENT __pSuper_handle rs
DW __main
DW __pSuper_handle r$main$filename = __pSuper_handle r
DW __main_unwrap
..CODE
__pSuper_handle r:
; code for the catch handler
catch (Base*) { ...
..DATA SEGMENT __pBase_handler s
DW __main
DW __pSuper_handle r$main$filename = __pSuper_handle r
DW __main_unwrap
..CODE
__pSuper_handle r:
; code for the catch handler
. . .
..CODE
__main_unwrap:
; code to unwrap this function call level if no handler found
void Thrower() {
int i;
cin >i;
switch(i) {
case 1: throw (Base*) 0;
1. locate [immediate/next] caller's stack frame
2. within data segment named __pBase_handler s...
3. is current return address between __XXX and __XXX_unwrap?
* No, call __XXX_unwrap and go back to 1
* Yes, jump to __pSuper_handle r$XXX$filename
case 2:
throw (Super*) 0;
Likewise here, except that two tables (pBase and pSuper) need
to be scanned, because Super is a derived class [however, even
this can be determined thru static analysis]
- - -
Linker magic I mentioned in my original article is twofold:
1. Unwrappers are generated everywhere where throwers are
located. There may well be more than one thrower for any given
type, but the linker should not complain about them having the
same name in the name table (and instead combine these into one
function only).
2. Data segments containing pointers to catch handlers may come
from multiple compilation units; linker must be able to consolidate
these tables so that the scanner routine finds all handlers.
Feel free to ask if my [hastily written] description is insufficient.
Cheers!
- Risto -