隐藏符号时dynamic_cast失败

我有很多静态库。一个是static_lib_a.a。我创建了一个动态库dynamic_lib.so来将它们组合在一起。 在static_lib_a.a中,它使用xerces 3.1.1来解析xml。以下是static_lib_a.a中的代码片段
xerces::DOMElement *pElementNode = dynamic_cast<xerces::DOMElement *>(pNode);
pNode的类型是xerces :: DOMNode。它被分配给xerces :: DOMElement的对象。这行代码将进行向下转换。 为了隐藏dynamic_lib.so中static_lib_a.a的所有符号,我使用-fvisibility = hidden来构建这个静态库。我发现如果添加-fvisibility = hidden,pElementNode将在运行时返回NULL指针。 gcc编译器的版本是3.4.4。 有没有人之前有类似的问题?     
已邀请:
您可以在gcc wiki的“C ++异常问题”一节中描述问题的根源。确保按照那里的“模糊链接”链接阅读有关虚拟表和typeinfo的部分。 这一切都适用于您的情况,因为类
xerces::DOMNode
xerces::DOMElement
不包含非纯的非内联虚函数(实际上这些类完全包含在头文件中)。这意味着任何类的虚拟表都会在包含其标头的每个目标文件中发出。 dynamic_cast正常工作所需的任一类的typeinfo符号都在与虚拟表相同的对象中发出,即在包含其标题的每个目标文件中发出。 当您使用隐藏的可见性标记库时,static_lib_a.a中对象中的
xerces::DOMNode
xerces::DOMElement
的所有typeinfo符号都被标记为隐藏。正如维基页面指出的那样,这可以确保链接器将其标记为在dynamic_lib.so中隐藏,并且您的dynamic_cast将失败。     
使用隐藏可见性是确保仅通过指定访问点使用库的好方法。如果您修改它,这是一个巨大的优势,因为您确切地知道您的库如何在外部使用,因此限制了您可能会破坏的内容。 它是一种非常类似于Windows的技术,使你可以将declspec作为DLL的可访问部分的一部分,除非您导入或导出时没有说明的细微差别,因此您的库可能正在制作“可见”函数使用而非实现。 尽管如此,为了回答您的问题,我认为只有第四版支持可见性。当然我们在这里使用它
#if defined(__GNUC__) && __GNUC__ >= 4
当您使用隐藏的可见性时,您需要明确说明您希望看到哪些符号。所以你有这个:
__attribute__((visibility("default")))
您可能会#define更具可读性,也许SO_EXPORT因此:
#define SO_EXPORT __attribute__((visibility("default")))
定义类:
class SO_EXPORT MyAccessInterface;
和方法类似:
SO_EXPORT int doSomething( parameters );
实际上,我们还有一个类似的隐藏可见性宏(如上所述,但使用“隐藏”而不是“默认”)。因此,即使我们对整个项目使用“默认”可见性,我们也可以隐藏一些实现细节。
#define SO_HIDDEN __attribute__((visibility("hidden")))
class SO_HIDDEN MyClassImpl;
    
dynamic_cast
要求派生类的typeinfo节点指向基类的typeinfo节点,这是通过动态重定位完成的。如果typeinfo节点的符号不可见,则包含派生类的节点的模块将拥有自己的副本,然后dynamic_cast假定这些类来自不同的树并禁止强制转换。 您需要添加一个属性,声明基类定义的默认可见性。     

要回复问题请先登录注册