【问题标题】:g++ linker error--typeinfo, but not vtableg ++链接器错误--typeinfo,但不是vtable
【发布时间】:2011-02-23 22:24:50
【问题描述】:

我知道有关缺少 typeinfo 的链接器错误的标准答案通常还涉及 vtable 和一些我忘记实际定义的虚函数。

我很确定这次不是这种情况。

这是错误:

UI.o:在 Graphics::Widgets::WidgetSet' 的函数 boost::shared_ptr<Graphics::Widgets::WidgetSet>::shared_ptr<Graphics::Resource::GroupByState>(boost::shared_ptr<Graphics::Resource::GroupByState> const&, boost::detail::dynamic_cast_tag)': UI.cpp:(.text._ZN5boost10shared_ptrIN8Graphics7Widgets9WidgetSetEEC1INS1_8Resource12GroupByStateEEERKNS0_IT_EENS_6detail16dynamic_cast_tagE[boost::shared_ptr<Graphics::Widgets::WidgetSet>::shared_ptr<Graphics::Resource::GroupByState>(boost::shared_ptr<Graphics::Resource::GroupByState> const&, boost::detail::dynamic_cast_tag)]+0x30): undefined reference totypeinfo 中

对令人讨厌的损坏名称运行 c++filt 表明它实际上正在查看 .boost::shared_ptr::shared_ptr(boost::shared_ptr const&, boost::detail::dynamic_cast_tag)

继承层次结构看起来像

class AbstractGroup
{
   public:
      virtual ~AbstractGroup();
      typedef boost::shared_ptr<AbstractGroup> Ptr;
      ...
};

class WidgetSet : public AbstractGroup
{
    public:
       virtual ~WidgetSet();
       typedef boost::shared_ptr<WidgetSet> Ptr;
       ...
};

class GroupByState : public AbstractGroup
{
    public:
       virtual ~GroupByState();
       ...
};

然后是这个:

class UI : public GroupByState
{
    public:
       virtual ~UI();
       ...
       void LoadWidgets( GroupByState::Ptr resource );
       ...
};

那么原来的实现:

void UI::LoadWidgets( GroupByState::Ptr resource )
{
   WidgetSet::Ptr tmp( boost::dynamic_pointer_cast< WidgetSet >(resource) );
   if( tmp )
   {
       ...
   }
}

我的愚蠢错误(试图转换为具有共享父级的同级类),即使错误有点神秘。

改为:

void UI::LoadWidgets( AbstractGroup::Ptr resource )
{
   WidgetSet::Ptr tmp( boost::dynamic_pointer_cast< WidgetSet >(resource) );
   if( tmp )
   {
       ...
   }
}

(我很确定这是我真正想要做的)给我留下了一个非常相似的错误:

UI.o:在 Graphics::Widgets::WidgetSet 的函数 boost::shared_ptr<Graphics::Widgets::WidgetSet>::shared_ptr<Graphics::_Drawer::Group>(boost::shared_ptr<Graphics::_Drawer::Group> const&, boost::detail::dynamic_cast_tag)': UI.cpp:(.text._ZN5boost10shared_ptrIN8Graphics7Widgets9WidgetSetEEC1INS1_7_Drawer5GroupEEERKNS0_IT_EENS_6detail16dynamic_cast_tagE[boost::shared_ptr<Graphics::Widgets::WidgetSet>::shared_ptr<Graphics::_Drawer::Group>(boost::shared_ptr<Graphics::_Drawer::Group> const&, boost::detail::dynamic_cast_tag)]+0x30): undefined reference totypeinfo 中 collect2: ld 返回 1 个退出状态

dynamic_cast_tag 只是 boost/shared_ptr.hpp 中的一个空结构。只是猜测 boost 可能与错误有任何关系。

传入 WidgetSet::Ptr 完全消除了强制转换的需要,并且构建良好(这就是为什么我认为这个问题的标准答案比标准答案更多)。

显然,我删除了很多可能很重要的细节。我的下一步是将其缩减为无法构建的最小示例,但我想我会尝试偷懒的方法并先在这里尝试一下。

TIA!

编辑:显示人们评论过的更多细节

【问题讨论】:

  • 在下面添加@Drew Hall 的答案。dynamic_cast 需要存储在 vftable 中的 RTTI,但由于您没有任何虚拟方法,因此没有地方存储。
  • 也许你应该要求赏金。

标签: c++ boost dynamic linker typeinfo


【解决方案1】:

没有看到你的整个 AbstractGroup 类很难确定,但听起来你的类层次结构中可能没有任何虚函数。尝试在 AbstractGroup 中定义一个虚拟析构函数(即使是内联的也可以),看看这是否会有所作为。没有单个虚函数,就没有 vtable,也就没有地方可以挂 typeinfo 数据。

【讨论】:

  • 对不起,我应该证明这一点。每个类肯定有虚拟成员。
【解决方案2】:

成员是私人的吗?如果是这样,请尝试在您的班级成员之前添加protected:

class AbstractGroup
{
protected:
   typedef boost::shared_ptr<AbstractGroup> Ptr;
   ...
};


class WidgetSet : public AbstractGroup
{
protected:
    typedef boost::shared_ptr<WidgetSet> Ptr;
  ...
};

回到您的代码示例后,出现了另一件事。看起来您尝试使用多态性。唯一的问题是您将共享指针对象动态转换为 WidgetSet。在阅读了一些documentation 之后,我相信您应该写resource.get_pointer(),因为您想将指针转换为shared_ptr 对象而不是shared_ptr 对象本身。我对 boost 不是很熟悉,所以请告诉我这是否有意义!

【讨论】:

  • 我原本应该展示的另一个细节:所有这些作品都是公开的。 Boost 通过添加 dynamic_pointer_cast 作为标准 dynamic_cast 的包装器做了一些魔术。您所描述的似乎是一个相当普遍的错误,这可能是他们首先发挥这种魔力的原因。如果您执行 get(),对其进行 dynamic_cast,然后将其分配给另一个 shared_ptr,它最终会被删除两次。
猜你喜欢
  • 2012-08-11
  • 2015-01-18
  • 2012-06-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-30
  • 1970-01-01
  • 1970-01-01
  • 2017-01-23
相关资源
最近更新 更多