简体   繁体   English

Linux上的RTLD_LOCAL和dynamic_cast

[英]RTLD_LOCAL and dynamic_cast on Linux

We have a plugin that is constructed of a few shared libraries in our application that we need to update while the application is running. 我们有一个插件,它由我们的应用程序中的一些共享库构成,我们需要在应用程序运行时更新它们。 For performance reasons we load and start using the new plugin before unloading the old plugin and only when all threads are done using the old plugin we unload it. 出于性能原因,我们在卸载旧插件之前加载并开始使用新插件,并且只有当使用旧插件完成所有线程时,我们才会卸载它。 Since the libraries of the new plugin and the old plugin have the same symbols in them we dlopen() with RTLD_LOCAL . 由于新插件的库和旧插件在其中具有相同的符号,因此我们使用RTLD_LOCAL dlopen() If we don't the new plugin call from internal functions by accident to symbols from the old plugin. 如果我们没有新的插件从内部函数调用到旧插件的符号。

One library of the plugin does dynamic_cast() to an object that was created by another library of the plugin. 该插件的一个库将dynamic_cast()传递给由插件的另一个库创建的对象。 This works on HP-UX, AIX, Solaris and Windows but not on Linux. 这适用于HP-UX,AIX,Solaris和Windows,但不适用于Linux。 As far as I can understand this is because all these OSs (compliers) use the name of the class to compare types (in the dynamic_cast() ) but Linux uses name strings addresses to do this comparison (to improve performance) and since each library has its own type_info object (since it was loaded with RTLD_LOCAL ) the addresses are different and therefore equal types seems to be non equal to the dynamic_cast() . 据我所知,这是因为所有这些操作系统(编译器)都使用类的名称来比较类型(在dynamic_cast() ),但是Linux使用名称字符串地址来进行这种比较(以提高性能)并且因为每个库有自己的type_info对象(因为它加载了RTLD_LOCAL ),地址是不同的,因此相等的类型似乎不等于dynamic_cast()

Is there a way to do one of the following: 有没有办法做到以下之一:

  • Make only the type_info objects be loaded as if RTLD_GLOBAL was supplied. 只加载type_info对象,就好像提供了RTLD_GLOBAL
  • Make the compiler use class name comparison instead of type_info addresses for comparing between types. 使编译器使用类名比较而不是type_info地址来进行类型之间的比较。

? The compiler we are using is: 我们使用的编译器是:

$ icpc -V
Intel(R) C++ Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 12.0.0.084 Build 20101006
Copyright (C) 1985-2010 Intel Corporation.  All rights reserved.

Ok, what we finally did is kind of worked around the problem. 好吧,我们最终做的是解决这个问题。

We added to the classes that we want to dynamic_cast() two static functions: 我们添加了我们想要的类dynamic_cast()两个静态函数:

static MyClass* doNew();
static MyClass* doDynCast(MyBase*);

These were implemented in the cpp file which kept the new , the dynamic_cast() and the type_info object in the same lib and thus making the dynamic_cast() work around the problem. 这些是在cpp文件中实现的,它将newdynamic_cast()type_info对象保存在同一个lib中,从而使dynamic_cast()能够解决问题。

This solution was enough for our specific case but if anyone has a more general solution it will be welcomed. 这个解决方案足以满足我们的特定情况,但如果有人有更通用的解决方案,那么将受到欢迎。

Another option that we found is to put all the implementation of the class in the cpp file which make the typeinfo symbol be present only in one library and all other libraries reference it only. 我们发现的另一个选项是将类的所有实现放在cpp文件中,这使得typeinfo符号只出现在一个库中,而所有其他库只引用它。 This results in a successful dynamic_cast() . 这导致成功的dynamic_cast()

Unfortunately, because type_info structures are weak symbols local to the library that creates them, it's not easily possible to make dynamic_cast work. 不幸的是,因为type_info结构是创建它们的库本地的弱符号,所以不可能使dynamic_cast工作。 You might try manipulating where the class vtable (and type_info) is instantiated however; 您可以尝试操作类vtable(和type_info)实例化的位置; on GCC, this can be done by ensuring the first non-inline function in the class (in order of definition) is defined only in the common shared dependency library. 在GCC上,这可以通过确保类中的第一个非内联函数(按照定义的顺序)仅在公共共享依赖库中定义来完成。 If your class has no non-inline functions, create a dummy one just to force this generation to occur. 如果您的类没有非内联函数,请创建一个虚拟函数以强制执行此生成。 Note however, that I haven't tested this and so can't guarantee that it will work. 但请注意,我没有对此进行测试,因此无法保证它能够正常工作。 Additionally, this is compiler-dependent; 另外,这是依赖于编译器的; I don't know what Intel's compiler does. 我不知道英特尔的编译器做了什么。

You could, of course, implement your own alternate dynamic casting mechanism using class names instead; 当然,您可以使用类名实现自己的备用动态转换机制; there are a number of libraries which do this as well, such as Qt's qobject_cast . 有许多库也可以这样做,比如Qt的qobject_cast

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM