当前位置: 首页 > 面试题库 >

与dlopen / dlsym一起使用时dynamic_cast失败

张嘉
2023-03-14
问题内容

介绍

让我为这个长期的问题表示歉意。它要尽我所能,但是很不幸,它不是很短。

设定

我定义了两个接口A和B:

class A // An interface
{
public:
  virtual ~A() {}

  virtual void whatever_A()=0;
};

class B // Another interface
{
public:
  virtual ~B() {}

  virtual void whatever_B()=0;
};

然后,我有一个共享库“ testc”,它构造类C的对象,实现A和B,然后传递指向其A接口的指针:

class C: public A, public B
{
public:
  C();
  ~C();

  virtual void whatever_A();
  virtual void whatever_B();
};

A* create()
{
  return new C();
}

最后,我有一个第二共享库“TESTD”,需要一个A*作为输入,并尝试将其转换为一个B*,使用dynamic_cast

void process(A* a)
{
  B* b = dynamic_cast<B*>(a);
  if(b)
    b->whatever_B();
  else
    printf("Failed!\n");
}

最后,我有一个主要应用程序,A*在库之间传递:

A* a = create();
process(a);

如果我构建主应用程序,并链接到“ testc”和“
testd”库,那么一切都会按预期进行。但是,如果我修改主应用程序以不链接到’testc’和’testd’,而是使用dlopen/
在运行时加载它们dlsym,则dynamic_cast失败。

我不明白为什么。有什么线索吗?

附加信息

  • 使用gcc 4.4.1,libc6 2.10.1(Ubuntu 9.10)进行了测试
  • 可用的示例代码

问题答案:

我在这里找到了问题的答案。据我了解,我需要将’testc’中的typeinfo提供给’testd’库。要在使用时执行此操作dlopen(),还需要做两件事:

  • 链接库时,请向链接器传递-E选项,以确保将所有符号导出到可执行文件,而不只是导出未在其中解析的符号(因为没有)。
  • 使用加载库时dlopen(),请添加RTLD_GLOBAL选项,以确保导出的符号testc也可用于testd


 类似资料:
  • 当试图将EnumTypeAdapter与Proguard一起使用时,它会在gson.getAdapter()中导致AssertionError。此错误似乎是由于类型信息丢失...以下是所有相关源代码: 例外情况: 正在使用的EnumTypeAdapter: 如何构造GSON对象: 我的ProGuard配置: 如前所述,我怀疑由于丢失了类型信息而出现了故障--在深入研究了GSON源代码后,这是用来解

  • 我试图将Hibernate与我的spring应用程序上下文联系起来。我正在成功地连接SessionFactory,但当我尝试调用getCurrentSession时,我看到以下错误: 我正在配置数据源会话工厂和事务管理器。我还指定了事务处理将是注释驱动的 下面是我的上下文XML: null 下面是我发现错误的类: 当这被称为sessionFactory时不是null,而是带有上述错误的错误。如果我

  • 我有一个带有Spring(5.7.2)Web/Security的REST API项目。 我只有一个表,它包含一个id和一个名称。 当我删除光盘时,我的DiscsService会 当我需要插入或更新时,我会: 我了解到,当您希望在同一事务中使用值(提交之前)时,将使用,并且将同步并清空SQL缓存。 在我的例子中,我看到我在数据库中插入/更新或删除了值。 我应该使用flush()(我认为不应该),但可

  • 我正在尝试使用MediaCodec和Surfaces对一部电影进行编码(像素缓冲区模式工作,但性能不够好)。但是,每次尝试调用时,它都会失败,因为并且因此,总是返回-1() 我看过Bigflake和Grafika的例子,我有另一个工作项目,在那里一切都是好的,但我需要在另一个稍微不同的设置下工作。 我目前有一个GLSurfaceView,它执行屏幕呈现,并随自定义EGLContextFactory

  • 问题内容: 作为此后C插件系统的继续:符号查找错误,我仍在编写我的插件系统,并遇到了新的错误。 概括一下插件是什么,该程序包含一个由外壳接口的网络应用程序,消息具有类型,因此可用于在网络上创建应用程序。例如,可能的应用程序是聊天或转移应用程序。 因此,shell命令可以在网络上发送特定应用程序的消息,当接收到一条消息时,如果它对应于特定应用程序,则将消息内容作为参数执行一个动作功能,它可能就是该应

  • 我有一个烧瓶服务器运行在http://127.0.0.1:5000和一个vuejs前端运行http://localhost:8080我已经做了api,并用postman测试了它,一切都如预期的那样工作:( > 将请求发布到/登录- (将请求发送至/登录)- 烧瓶API代码: 登录。vue: 指数vue 当我使用邮递员登录时,我得到的响应为;当我使用邮递员获取url/索引时,我得到响应。数据但当我使