C++ 最简单的 RTTI 实现是什么?

发布于 2024-07-26 06:55:26 字数 276 浏览 3 评论 0原文

我正在尝试为嵌入式操作系统实现异常处理,但我一直困惑于如何检测抛出的“异常”的类型(以选择适当的处理程序)。

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

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

-- 编辑 --

我不在编译器上工作,它是 ia32-g++。

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

坏尐絯℡ 2024-08-02 06:55:26

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

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

对于许多使用 C++ ABI 的编译器来说都是如此 - 这里有一个相关的问题

如果是这样,您可能可以像这样获取vtable:

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

然后您可以比较两个对象指针的vtable,看看它们是否指向相同类型的对象。

因此,“类型开关”(catch 基本上就是这样)会执行类似以下操作:

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 。 这意味着为了区分两种异常类型,它们必须各自重写一个虚函数,以确保它们拥有自己的虚函数表。

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

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.

时光病人 2024-08-02 06:55:26

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文