Question

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

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top