2009-07-03 34 views
8

我想实现一个嵌入式操作系统的异常处理,我被困在如何检测抛出的“异常”(选择适当的处理程序)的类型。C++最简单的RTTI实现是什么?

异常处理的保存和恢复上下文部分已经完成,但由于无法检测到抛出的“异常”的类型,我无法拥有特定的句柄。 C++的标准RTTI实现过于依赖于其他库,因此我目前正在考虑它不可用。

考虑到我的目标是一个嵌入式系统,因此我无法创建很多代码,我可以获取(或制作)的“运行时类型信息”的最小实现是什么?

- 编辑 -

我没有编译器工作,这是一个IA32-G ++。

+1

你在编写/修改编译器还是语言运行时,或者你准备将它放在哪里?多一点上下文会很好。 – jalf 2009-07-03 23:31:02

+0

如果您的内存有限,则不应启用RTTI,甚至不要尝试使用例外情况。最好考虑一种替代方法。 – 2009-07-04 13:24:56

+0

如果抛出了一个异常,抛出抛出异常以某种方式编码异常类型信息,所以我不明白为什么你需要一些“替代”方法。正如贾尔夫所说,给我们更多关于你实际上想要做什么的信息。 – 2009-07-04 19:16:49

回答

11

当您在嵌入式环境中工作时,您可能会偏好极小的解决方案,并且可以利用有关编译器的非标准或不可移植的事实。

如果一个类在C++中是多态的(至少有一个自己的虚函数),它可能有一个指向其中某个嵌入的vtable的指针。这可能是vtable指针出现在对象的内存布局开始处。

很多编译器,使用C++ ABI - a related SO question here都是如此。

如果是这样,你可能能够在虚表像这样得到:

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

然后,你可以比较两个指针到对象的虚函数表,看看他们是否指向同一类型对象。

因此,一个“型开关”(这是什么捉基本上是)会做这样的事情:

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

可以隐藏在CATCH宏模式。

重要点 - 如果您从基类派生类,但派生类不重写任何虚函数或添加任何新的虚函数,那么编译器可以为派生类重用基类的vtable。这意味着为了区分两种异常类型,它们必须重写一个虚拟函数,以确保它们拥有自己的vtables。

请注意,这只是异常处理涉及的一小部分。还有一个小问题就是解开堆栈!跳转到处理程序时,需要调用堆栈中所有对象的析构函数。这不仅仅是做setjmp/longjmp的问题。

2

我能想到的最简单的RTTI是从具有纯虚拟“GetType()”功能的公共基础派生所有类。要么让它返回一个字符串或创建一个包含所有类型的巨大枚举。它非常简单,速度快,内存开销小。然而,并不特别灵活。

相关问题