我很高兴发布另一个对一个非常古老的问题的答案,但我今天遇到了它,并想指出到目前为止给出的答案在所有方面都不准确。
如果您的代码使用的库本身使用 RTTI 信息,则可能会出现潜在问题。
下面的代码就是一个简单的例子:
#include <stdio.h>
// Library header
struct A { virtual void fn(); };
struct B : A { virtual void fn(); };
void lib_fn(A* ptr);
// Library code
#ifdef LIB
void A::fn() { puts("a"); }
void B::fn() { puts("b"); }
void lib_fn(A* ptr)
{
if (B* b = dynamic_cast<B*>(ptr))
puts("successful dynamic_cast");
ptr->fn();
}
#endif
// Application code
#ifdef APP
struct C : B
{
virtual void fn()
{ puts("c"); }
};
int main()
{
C obj;
lib_fn(&obj);
return 0;
}
#endif
这里我们有一个提供许多类的库。它是用 RTTI 编译的,因为它在内部使用了dynamic_cast,但我们不知道这一点(我们没有阅读源代码,库文档中也没有提到)。以下命令可用于创建库:
g++ -shared -o libmodule.so -fPIC code.cpp -DLIB
我们也有我们的应用程序。我们子类化一个库类,并将 this 的一个实例传递给一个库函数。我们在没有 RTTI 的情况下编译我们的应用程序,因为我们想节省空间,而且我们不喜欢 RTTI 在我们的应用程序二进制文件中提取有关我们类名称的信息这一事实。要创建使用该库的应用程序可执行文件:
g++ -s -fno-rtti -o app code.cpp -DAPP -L. -lmodule -Wl,-rpath,.
使用-fno-rtti 编译的此应用程序将崩溃,因为该应用程序不包含 RTTI 信息,即使它本身不使用它,库也会使用它。
如果这是一个第三方库,则可能无法确定它不会以可能影响您的代码的方式使用 dynamic_cast。更糟糕的是,它可能不是今天,但它可能会在未来被替换为一个版本,此时应用程序将然后开始崩溃。