views:

938

answers:

2

I'm trying to implement exception handling for an embedded OS and I'm stuck at how to detect the type of the thrown "exception" (to select the appropriate handler).

The saving and restoring context parts of the exception handling are already done, but I can't have specific handles since I can't detect the type of the thrown 'exception'. The standard RTTI implementation of c++ is too dependent of other libraries and for that reason I'm currently considering it unavailable.

Considering that my target is an embedded system and for that reason I can't create much code, what is the smallest implementation of "Runtime Type Information" I can get (or make)?

-- Edit --

I'm not working on the compiler, It's an ia32-g++.

+1  A: 

The simplest RTTI I can think of is to derive all classes from a common base that have a pure virtual "GetType()" function. Either get it to return a string or create a huge enum with all the types in it. Its pretty simple, its quick and has low memory overhead. Not particularly flexible, however.

Goz
Of course, for virtual functions to exist, you probably use some sort of virtual-function-pointer-table. Which somehow could be made to be used for rtti...
gimpf
a tad more involved than the giant enum method though ;)
Goz
Should add its a tad less cross platform as well... finding those VTables can be bloody hard work.
Goz
What I meant: How to do an abstract virtual function GetType() without using some sort of vfptrtable? You say, you implement RTTI with virtual functions, but for virtual functions you already need some sort of RTTI.
gimpf
Well, I think it is a little bit out of reach. There are too many objects in the system. But for smaller and kind of "static" development it is a good alternative.
freitass
+5  A: 

As you're working in an embedded environment, you presumably favour extremely minimal solutions and you can take advantage of non-standard or non-portable facts about your compiler.

If a class is polymorphic (has at least one virtual function of its own) in C++, it probably has a pointer to a vtable embedded somewhere in it. It may be that the vtable pointer appears at the beginning of the object's layout in memory.

This is true of many compilers, ones that use the C++ ABI - a related SO question here.

If so, you might be able to get at the vtable like this:

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

Then you can compare the vtables of two pointers-to-objects to see if they point to the same type of object.

So a "type switch" (which is what catch basically is) would do something like this:

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...
}

You could hide that pattern in a CATCH macro.

Important point - if you derive a class from a base, but the derived class does not override any virtual functions or add any new virtual functions, then the compiler could conceivably reuse the base class's vtable for the derived class. This means that in order to distinguish between two exception types, they must each override a virtual function, to ensure that they have their own vtables.

Note that this is only a tiny fraction of what exception handling involves. There is also the small matter of unwinding the stack! You need to call the destructors of all objects on the stack when you jump to the handler. It's not just a matter of doing setjmp/longjmp.

Daniel Earwicker
Can you show a way to get the 'ptr' in the first code? And I didn't understand the 'obj' role too.
freitass
Sorry, that was a typo. It's just a pointer to an object of a polymorphic type.
Daniel Earwicker